P214
41.数据流中的中位数
class Solution {
public:
vector<int> maxHeap;
vector<int> minHeap;
void Insert(int num)
{
int minSize = minHeap.size(), maxSize = maxHeap.size();
if( (minSize+maxSize)%2){ // 判断偶数奇数,注意用%
// 放入最小堆
if( maxSize >0 && num<maxHeap[0]){
maxHeap.push_back(num);
push_heap(maxHeap.begin(),maxHeap.end(),less<int>());
num = maxHeap[0];
pop_heap(maxHeap.begin(),maxHeap.end(),less<int>());
maxHeap.pop_back();
}
minHeap.push_back(num);
push_heap(minHeap.begin(),minHeap.end(),greater<int>());
}else{
// 放入最大堆
if(minSize>0 && num> minHeap[0]){
minHeap.push_back(num);
push_heap(minHeap.begin(),minHeap.end(),greater<int>());
num = minHeap[0];
pop_heap(minHeap.begin(),minHeap.end(),greater<int>());
minHeap.pop_back();
}
maxHeap.push_back(num);
push_heap(maxHeap.begin(),maxHeap.end(), less<int>());
}
}
double GetMedian()
{
int minSize = minHeap.size(), maxSize = maxHeap.size();
if( minSize+maxSize==0) return 0.0;
if( (minSize+maxSize)&1){
return maxHeap[0];
}else{
return (maxHeap[0]+minHeap[0])/2.0;
}
}
};
使用优先队列
class Solution {
public:
priority_queue<int,vector<int>, less<int> > max;
priority_queue<int,vector<int>,greater<int> > min;
void Insert(int num)
{
int maxSize = max.size(), minSize = min.size();
if((maxSize+minSize)&1){
// 放入min
if(maxSize>0 && num< max.top()){
max.push(num);
num = max.top();
max.pop();
}
min.push(num);
}else{
// 放入max
if(minSize >0 && num > min.top()){
min.push(num);
num = min.top();
min.pop();
}
max.push(num);
}
}
double GetMedian()
{
int maxSize = max.size(), minSize = min.size();
if(maxSize+minSize==0) return 0.0;
if((maxSize+minSize)&1) return max.top();
else return (max.top()+min.top())/2.0;
}
};
P218
42. 连续子数组的最大和
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
int n = array.size();
if(n==0) return 0;
int res = array[0];
int tmp=array[0];
for(int i=1;i<n;i++){
if( tmp + array[i] < array[i]){ // 新的序列的开始
tmp = array[i];
}
else{
tmp += array[i]; // 原有序列的延续
}
res = max(res,tmp);
}
return res;
}
};
P221
43. 1~n整数中1出现的次数
https://www.cnblogs.com/xuanxufeng/p/6854105.html
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{ int a, b;
int res = 0;
for(long m = 1; m<=n;m*=10){
a = n/m;
b= n%m;
res += (a+8)/10*m+((a%10==1)?b+1:0);
}
return res;
}
};
P225
44. 数字序列中某一位的数字
此题调试了很久,最终发现问题在于 pow()函数,因此 还是自己实现吧
#include <iostream>
using namespace std;
int countOfIntegers(int digits){
if(digits==1) return 10;
else{
int tmp =1;
for(int i=0; i< digits-1;i++)
tmp *= 10;
return 9*tmp;
}
}
int findDigit(int index, int digits){
int startNum;
if(digits==1){
startNum = 0;
}
else{
startNum = 1;
for(int i=0; i< digits-1;i++)
startNum *= 10;
}
int number = startNum + index/digits;
int indexFromRight = digits - index%digits;
for(int i=0; i< indexFromRight-1;i++){
number = number/10;
}
return number%10;
}
int digitAtIndex(int index){
if(index<0)
return -1;
int digits = 1; // 位数
while(true){
int numbers = countOfIntegers(digits); // 位数确定的情况下,有多少整数
if(index < numbers*digits){ // 位数确定的情况下,容许的范围 0 ~ numbers*digits-1
return findDigit(index, digits);
}
else {
// 在新的查找范围内的新的索引
index = index - numbers*digits;
digits++;
}
}
}
int main(){
cout<<digitAtIndex(0); // 0
cout<<digitAtIndex(1); // 1
cout<<digitAtIndex(9); // 9
cout<<digitAtIndex(10); // 1
cout<<digitAtIndex(189); // 9
cout<<digitAtIndex(190); // 1
cout<<digitAtIndex(1000); // 3
cout<<digitAtIndex(1001); // 7
cout<<digitAtIndex(1002); // 0
return 0;
}
P227
45. 把数组排成最小的数
class Solution {
public:
static bool compare(int a, int b){
string strNum1 = to_string(a);
string strNum2 = to_string(b);
return (strNum1+strNum2)<(strNum2+strNum1);
}
string PrintMinNumber(vector<int> numbers) {
string res = "";
int n = numbers.size();
if(n==0) return res;
sort(numbers.begin(),numbers.end(),compare);
for(int i=0;i<n;i++){
res += to_string(numbers[i]);
}
return res;
}
};
重点在于为何这样得到的就是最小数呢,请给出证明
P231
46. 把数字翻译成字符串
https://www.jianshu.com/p/80e1841909b7
#include <iostream>
using namespace std;
int countNum(string & number){
int len = number.length();
int counts[len];
for(int i=0;i<len;i++)
counts[i]=0;
for(int i=len-1;i>=0;i--){
if(i==len-1) counts[i]=1;
else
counts[i] += counts[i+1];
if( i< len-1){
int digit1 = number[i]-'0';
int digit2 = number[i+1]-'0';
int value = 10*digit1 + digit2;
if(value>=10 && value<=25){
if(i<len-2)
counts[i] += counts[i+2];
else
counts[i]+=1;
}
}
}
return counts[0];
}
int GetTranslationCount(int number){
if(number<0) return 0;
string str = to_string(number);
return countNum(str);
}
int main(){
cout<<GetTranslationCount(12258);
return 0;
}
P233
47. 礼物的最大价值
典型的用动态规划解决的问题
#include <iostream>
#include <vector>
using namespace std;
int getMaxValue (vector<int> mat, int row, int col){
int n = mat.size();
if(n==0) return 0;
int res[n];
for(int i=0;i<n;i++) res[i] = mat[i];
for(int i=0;i<row;i++){
for(int j=0; j<col;j++ ){
// 对应到 i*col+j
// 左边
int a = 0;
if(j>0) a = res[i*col+j-1];
// 右边
if(i>0) a = max(a, res[(i-1)*col+j]);
res[i*col+j] += a;
}
}
return res[n-1];
}
int main(){
int mat[16]={1,10,3,8,12,2,9,6,5,7,4,11,3,7,16,5};
vector<int> v(mat,mat+16);
cout<<getMaxValue( v ,4,4);
return 0;
}
进一步优化,只开辟 int res[col]
P236
48.最长不含重复字符的子字符串
https://leetcode.com/problems/longest-substring-without-repeating-characters/description/
下面对应leetcode, 不局限于字母
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.empty()) return 0;
int len = s.length();
int dp[len];
int position[255]; // 用于记录字母最新出现的位置
for(int i=0;i<255;i++)
position[i]=-1;
dp[0]=1;
position[s[0]]=0;
int maxlen = 1;
for(int i=1;i<len;i++){
if(position[s[i]]==-1){
dp[i]=dp[i-1]+1;
}else{
if( i-position[s[i]]>dp[i-1]){
dp[i] = dp[i-1]+1;
}else{
dp[i] = i-1-position[s[i]]+1;
}
}
position[s[i]]=i;
if(dp[i]>maxlen)
maxlen = dp[i];
}
return maxlen;
}
};
P240
49.丑数
每一个丑数是由其他某个丑数乘2 或3 或5得到的
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if(index==0) return 0;
int res[index];
res[0]=1;
int t2=0,t3=0,t5=0;
for(int i=1;i<index;i++){
res[i] = min(min(res[t2]*2,res[t3]*3),res[t5]*5);
if(res[i]==res[t2]*2)
t2++;
if(res[i]==res[t3]*3)
t3++;
if(res[i]==res[t5]*5)
t5++;
}
return res[index-1];
}
};
P243
50. 第一个只出现一次的字符
class Solution {
public:
int FirstNotRepeatingChar(string str) {
if(str.empty()) return -1;
int table[256];
for(int i=0;i<256;i++)
table[i]=0;
for(int i=0; i< str.length();i++)
table[str[i]]++;
for(int i=0;i<str.length();i++){
if(table[str[i]]==1)
return i;
}
return -1;
}
};
题目二:
class Solution
{
private:
int table[256];
int index=0;
public:
Solution():index(0){
for(int i=0;i<256;i++)
table[i]=-1;
}
//Insert one char from stringstream
void Insert(char ch)
{ index++;
if(table[ch]==-1)
table[ch]=index;
else
table[ch]=-2;
return ;
}
//return the first appearence once char in current stringstream
char FirstAppearingOnce()
{ int res = -1;
char ch='#';
for(int i=0;i<256;i++){
if(table[i]>=0){
if(res==-1){
ch = (char)i;
res = table[i];
}
else{
if(table[i]<res){
res = table[i];
ch = (char)i;
}
}
}
}
return ch;
}
};
P249
51.数组中的逆序对
https://www.nowcoder.com/questionTerminal/96bd6684e04a44eb80e6a68efc0ec6c5
class Solution {
public:
int InversePairs(vector<int> data) {
// 本质上,实现归并排序,复杂度O(nlogn),但是需要O(n)的空间
if(data.size()<=1) return 0;
vector<int> copy(data);
return InversePairsCore(data,copy,0,data.size()-1);
;
}
private:
int InversePairsCore(vector<int> & data, vector<int> & copy, int begin, int end){
if(begin==end){
copy[begin]=data[begin];
return 0;
}else{
int mid = (begin+end)/2;
int left = InversePairsCore(copy,data,begin,mid)%1000000007;
int right = InversePairsCore(copy,data,mid+1,end)%1000000007;
int cnt = 0;
int i = mid; // 前半段最后一个数字的下标
int j = end; // 后半段最后一个数字的下标
int indexCopy = end;
while(i>=begin && j>=mid+1){
if(data[i]>data[j]){
copy[indexCopy--] = data[i--];
cnt += j-(mid+1)+1;
cnt = cnt%1000000007;
}else{
copy[indexCopy--]=data[j--];
}
}
while(i>=begin){
copy[indexCopy--]=data[i--];
}
while(j>=mid+1){
copy[indexCopy--]=data[j--];
}
return (left+right+cnt)%1000000007;
}
}
};
P253
52.两个链表的第一个公共节点
方法一:
开辟了空间
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
map<ListNode *, int> m;
while(pHead1){
m[pHead1]=1;
pHead1 = pHead1->next;
}
while(pHead2){
if(m.count(pHead2)==1)
break;
else
pHead2=pHead2->next;
}
return pHead2;
}
};
方法二:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
int len1=0,len2=0;
ListNode * tmp1 = pHead1,*tmp2=pHead2;
while(tmp1){
len1++;
tmp1=tmp1->next;
}
while(tmp2){
len2++;
tmp2=tmp2->next;
}
if(len1>len2){
int step=len1-len2;
while(step){
pHead1 = pHead1->next;
step--;
}
}else{
int step = len2-len1;
while(step){
pHead2 = pHead2->next;
step--;
}
}
while(pHead1){
if(pHead1==pHead2){
break;
}
else{
pHead1=pHead1->next;
pHead2=pHead2->next;
}
}
return pHead1;
}
};
P263
53.在排序数组中查找数字(二分查找的加强版)
下面的方法和顺序统计的复杂度一样,是O(n), 面试官期待更高效的方法
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
if(data.empty()) return 0;
int index = binaryFind(data, k, 0,data.size()-1);
if(index==-1) return 0;
int cnt = 1;
int pre = index-1, post = index+1;
while(pre>=0){
if(data[pre]==k){
cnt++;
pre--;
}else{
break;
}
}
while(post<data.size()){
if(data[post]==k){
cnt++;
post++;
}else{
break;
}
}
return cnt;
}
private:
int binaryFind(vector<int> & data, int k, int begin, int end){
if(begin>end){
return -1;
}
int mid = (begin+end)/2;
if(k==data[mid])
return mid;
else if(k>data[mid]){
return binaryFind(data,k,mid+1,end);
}
else{
return binaryFind(data,k,begin,mid-1);
}
}
};
高效的解法:
用二分查找定位第一次出现的位置、第二次出现的位置
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
if(data.empty()) return 0;
int firstIndex = getFirstIndex(data,k,0,data.size()-1);
if(firstIndex==-1) return 0;
int lastIndex = getLastIndex(data,k,0,data.size()-1);
return lastIndex-firstIndex+1;
}
private:
int getFirstIndex(vector<int> & data, int k, int start, int end){
if(start>end)
return -1;
int mid = (start+end)/2;
if(data[mid]==k){
if(mid>0 && data[mid-1]==k){
return getFirstIndex(data,k,start,mid-1);
}else
return mid;
}else if(data[mid]>k){
return getFirstIndex(data,k,start,mid-1);
}else{
return getFirstIndex(data,k,mid+1,end);
}
}
int getLastIndex(vector<int> & data, int k, int start, int end){
if(start>end)
return -1;
int mid = (start+end)/2;
if(data[mid]==k){
if(mid< data.size()-1 && data[mid+1]==k){
return getLastIndex(data,k,mid+1,end);
}else
return mid;
}else if(data[mid]>k){
return getLastIndex(data,k,start,mid-1);
}else{
return getLastIndex(data,k,mid+1,end);
}
}
};
扩展:P266
题目:0~n-1中缺失的数字
#include<iostream>
#include<vector>
using namespace std;
int findIndex(vector<int> & data, int s, int e){
if(s>e) return -1;
int mid = (s+e)/2;
if(mid==data[mid]){
return findIndex(data,mid+1,e);
}else{
if(mid>0 && data[mid-1]==mid-1 || mid==0)
return mid;
else
return findIndex(data,s,mid-1);
}
}
int main(){
vector<int> data;
data.push_back(0);
data.push_back(1);
data.push_back(2);
data.push_back(4);
data.push_back(5);
int index = findIndex(data,0,4);
if(index==-1) cout<<data.size();
else cout<<index;
return 0;
}
扩展:P267
数组中数值和下标相等的元素
#include<iostream>
#include<vector>
using namespace std;
int findValue(vector<int> & data){
int left=0,right=data.size()-1,mid;
while(left<=right){
mid = (left+right)/2;
if(mid==data[mid]) return mid;
else if(data[mid]>mid){
right = mid-1;
}else{
left = mid+1;
}
}
return -1;
}
int main(){
vector<int> data;
data.push_back(-3);
data.push_back(-1);
data.push_back(1);
data.push_back(13);
data.push_back(15);
int value = findValue(data);
cout<<value;
return 0;
}
P269
54.二叉搜索树的第K大节点
!!!中序遍历二叉搜索树,得到的结果是递增排序的。
实现一:
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if(pRoot==NULL || k<1 ) return NULL; // 判断k<1很重要
vector<TreeNode *> res;
inOrder(res,pRoot);
if(res.size()<k) return NULL;
else return res[k-1];
}
private:
void inOrder(vector<TreeNode *> & v, TreeNode * node){
if(node->left) inOrder(v,node->left);
v.push_back(node);
if(node->right) inOrder(v,node->right);
}
};
实现二:
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if(pRoot==NULL || k < 1) return NULL;
TreeNode * ans = NULL;
inOrder(pRoot, ans,k);
return ans;
}
private:
void inOrder(TreeNode * pRoot, TreeNode * & ans, int & k){
if(pRoot->left) inOrder(pRoot->left, ans, k);
k--;
if(k==0) {
ans = pRoot;
return ;
}
if(pRoot->right) inOrder(pRoot->right,ans,k);
}
};
P271
55.二叉树的深度
题目一:二叉树的深度
方法一:树的层次遍历
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
int TreeDepth(TreeNode* pRoot)
{ if(pRoot==NULL) return 0;
queue<TreeNode * > q;
int cnt = 0;
q.push(pRoot);
TreeNode * tmp = NULL;
while(!q.empty()){
cnt++;
for(int i=0;i<q.size();i++){
tmp = q.front();
q.pop();
if(tmp->left) q.push(tmp->left);
if(tmp->right) q.push(tmp->right);
}
}
return cnt;
}
};
方法二:递归
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
int TreeDepth(TreeNode* pRoot)
{
if(pRoot==NULL) return 0;
return getDepth(pRoot);
}
private:
int getDepth(TreeNode * pRoot){
int left = 0;
if(pRoot->left) left = getDepth(pRoot->left);
int right = 0;
if(pRoot->right) right = getDepth(pRoot->right);
return max(left,right)+1;
}
};
题目二:平衡二叉树
https://leetcode.com/problems/balanced-binary-tree/submissions/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isBalanced(TreeNode* root) {
if(root==NULL) return true;
bool res = true;
getDepth(root,res);
return res;
}
private:
int getDepth(TreeNode * root, bool & res){
int left = 0;
if(root->left) left =getDepth(root->left,res);
int right = 0;
if(root->right) right = getDepth(root->right,res);
if(abs(right-left)>1) {
res = false;
}
return max(left,right)+1;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isBalanced(TreeNode* root) {
int init = 0;
return isBalancedTree(root,init);
}
private:
bool isBalancedTree(TreeNode * root, int & depth){ // depth表示当前节点的深度
if(root==NULL) {
depth=0;
return true;
}
int left =0,right=0;
if( isBalancedTree(root->left,left) && isBalancedTree(root->right,right)){
if(abs(left-right)>1) return false;
else{
depth = max(left,right)+1;
return true;
}
}
return false;
}
};
p275
56.数组中数字出现的次数 ---- 考察二进制与位运算
题目一:数组中只出现一次的两个数字
一个整型数组里除两个数字之外,其他数字都出现了两次,请找出这两个只出现一次的数字。要求时间复杂度O(n),空间复杂度O(1)
先考虑数组中只有一个数字出现了一次,其他数字出现了两次。
!!!任何数字异或它自己结果都等于0,从头至尾依次异或数组中的每个数,最后的结果是只出现一次的那个数
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int len = data.size();
if(len <2 ) return;
int res = 0;
for(int i=0;i<len;i++)
res ^= data[i];
int index;
int res1 = 0, res2=0;
index = findIndex(res);
for(int i=0;i<len;i++){
if( isOne(data[i],index))
res1 ^= data[i];
else
res2 ^= data[i];
}
*num1 = res1;
*num2 = res2;
}
private:
bool isOne(int value, int index){
int num=1;
num = num << (index-1);
if(value&num) return true;
else return false;
}
int findIndex(int & value){
int index = 1;
int num = 1;
while( (value&num) ==0){ // 注意加括号
index++;
num = num << 1;
}
return index;
}
};
P278
题目二:数组中唯一只出现一次的数字
在一个数组中除一个数字只出现一次之外,其他数字都出现了三次。
#include <iostream>
#include <vector>
using namespace std;
int FindNumberAppearingOnce(vector<int> numbers){
int len = numbers.size();
if(len <1 ) {
cout<<"invalid input";
return -1;
}
int bitSum[32]={0};
for(int i=0;i<len;i++){
int bitMask = 1;
for(int j=0;j<32;j++){
if(numbers[i]&bitMask) bitSum[j] += 1;
bitMask = bitMask << 1;
}
}
int res = 0;
for(int i=31;i>=0;i--){
res = res<<1;
res += bitSum[i]%3;
}
return res;
}
int main(){
vector<int> v;
v.push_back(2);
v.push_back(4);
v.push_back(3);
v.push_back(3);
v.push_back(3);
v.push_back(2);
v.push_back(2);
cout<<FindNumberAppearingOnce(v);
return 0;
}
P280
57.和为s的数字
题目一:和为S的两个数字
https://www.nowcoder.com/practice/390da4f7a00f44bea7c2f3d19491311b?tpId=13&tqId=11195&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
int len = array.size();
vector<int> ans;
int a,b;
bool flag = false;
int multiply;
int left = 0, right = array.size()-1;
while(left<right){
if(array[left]+array[right]==sum){
if(flag==false){
a = array[left];
b = array[right];
multiply = a*b;
flag = true;
}else{
if(array[left]*array[right]<multiply){
a = array[left];
b = array[right];
multiply = array[left]*array[right];
}
}
left++;
right--;
}else if(array[left]+array[right]<sum){
left++;
}else{
right--;
}
}
if(flag == true) {
ans.push_back(min(a,b));
ans.push_back(max(a,b));
}
return ans;
}
};
P282
题目二:和为S的连续正数序列
https://www.nowcoder.com/practice/c451a3fd84b64cb19485dad758a55ebe?tpId=13&tqId=11194&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int>> v;
int left = 1, right = 2;
int tmp;
vector<int> res;
while(left < right && right<=(sum+1)/2){
tmp = right*(right+1)/2 - left*(left-1)/2;
if(tmp == sum){
res.clear();
for(int i=left;i<=right;i++)
res.push_back(i);
v.push_back(res);
left++;
right++;
}else if(tmp > sum){
left++;
}else{
right++;
}
}
return v;
}
};
P284
58.翻转字符串
题目一:翻转单词顺序
class Solution {
public:
string ReverseSentence(string str) {
int start = 0, end = str.length()-1;
myReverse(str,start,end);
for(int i=0;i<str.length();i++){
if(str[i]==' '){
end = i-1;
myReverse(str,start,end);
start = i + 1;
}
}
if(str[str.length()-1]!=' ') // 翻转最后一个单词
myReverse(str,start,str.length()-1);
return str;
}
private:
void myReverse(string & str, int start, int end){
char tmp; // 注意用char
while(start < end){
tmp = str[end];
str[end] = str[start];
str[start] = tmp;
start++;
end--;
}
}
};
class Solution {
public:
string ReverseSentence(string str) {
int start = 0, end = str.length()-1;
myReverse(str,start,end);
start = end = 0;
while(start < str.length()){
if(str[start]==' '){
start++;
end++;
}else if(str[end]==' ' || end==str.length()){
myReverse(str,start,end-1);
start = end + 1;
end = start; // 让两者重逢
}else{
end++;
}
}
return str;
}
private:
void myReverse(string & str, int start, int end){
char tmp; // 注意用char
while(start < end){
tmp = str[end];
str[end] = str[start];
str[start] = tmp;
start++;
end--;
}
}
};
P287
题目二:左旋转字符串
class Solution {
public:
string LeftRotateString(string str, int n) {
int len = str.length();
if(len <= n || n<=0) return str;
myReverse(str, 0, len-1);
myReverse(str,0,len-n-1);
myReverse(str, len-n,len-1);
return str;
}
private:
void myReverse(string & str, int start, int end){
char tmp;
while(start < end){
tmp = str[end];
str[end] = str[start];
str[start]= tmp;
start++;
end--;
}
}
};
P288
59.队列的最大值
题目一:滑动窗口的最大值
参考:https://www.jianshu.com/p/3242ddf81428
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
vector<int> res;
int n = num.size();
if(size > n || size < 1) return res;
deque<int> index;
for(int i=0;i<size;i++){ // 只考虑第一个窗口
if(index.empty()){
index.push_back(i);
}else{
while(!index.empty() && num[index.back()]< num[i]){
index.pop_back();
}
index.push_back(i);
}
}
res.push_back(num[index.front()]);
for(int i = size; i < n; i++){ // 开始滑动
while(!index.empty() && num[index.back()] < num[i]){
index.pop_back();
}
index.push_back(i);
if(i-index.front()==size){ // 要滑出首端数字
index.pop_front();
}
res.push_back(num[index.front()]);
}
return res;
}
};
题目二:队列的最大值
P294
60. n个骰子的点数
方法一:递归
其实就是深度优先,把每条路径的和都求出来
#include <iostream>
using namespace std;
void gopath(int * record, int number,int sum,int n){
if(number==0) {
record[sum-n]++;
return ;
}
for(int i=1;i<=6;i++){
gopath(record, number-1,sum+i,n);
}
}
void printprob (int n){
if(n<1) return ;
int maxsum = 6*n;
int record[maxsum-n+1]={0};
gopath(record,n,0,n);
for(int i=0; i< maxsum-n+1;i++)
cout<<record[i]<<endl;
}
int main(){
printprob(2);
return 0;
}
方法二:基于循环,时间性能更好
P298
61. 扑克牌中的顺子
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
int n = numbers.size();
if(n == 0) return false;
sort(numbers.begin(),numbers.end());
int zero_cnt = 0;
for(int i=0;i<n;i++){
if(numbers[i]==0) zero_cnt++;
else{
if(i<n-1){
if(numbers[i+1]==numbers[i]) return false;
else{
zero_cnt = zero_cnt - (numbers[i+1]-numbers[i]-1);
if(zero_cnt<0) return false;
}
}
}
}
return true;
}
};
P300
62.圆圈中最后剩下的数字
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<=0 || m<=0) return -1;
int number[n];
for(int i=0;i<n;i++)
number[i]=0;
int cnt = n;
int index=0;
while(cnt>1){
for(int i=1;i<=m;i++){
while(number[index%n]==1){
index++;
}
if(i==m){
number[index%n]=1;
cnt--;
}
index++;
}
}
while(number[index%n]==1)
index++;
return index%n;
}
};
用vector
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<=0 || m<=0) return -1;
vector<int> v;
for(int i=0;i<n;i++)
v.push_back(i);
vector<int>::iterator it = v.begin(); // 注意先后顺序
while(v.size()>1){
for(int i=1;i<=m;i++){
if(it == v.end()){
it = v.begin();
}
if(i==m){
it = v.erase(it);
}else{
it++;
}
}
}
if(it == v.end()) it = v.begin(); // 这一行十分关键
return *it;
}
};
简单的方法,但是数学推导分析
https://blog.csdn.net/u010429424/article/details/73695062
f(n,m)表示最后剩下的数字
f(n,m) =( f(n-1,m)+m)%n
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<=0 || m<=0) return -1;
int before=0;
for(int i=2;i<=n;i++){
before = (before+m)%i;
}
return before;
}
};
P304
63.股票的最大利润
https://leetcode.com/problems/best-time-to-buy-and-sell-stock/submissions/
- Best Time to Buy and Sell Stock
只有一次交易,遍历数组,每遍历一个数表示当前被卖,那么只需记录当前之前的最小值(买入),两者做差看利益是否是最大。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int maxProfit = 0;
int n = prices.size();
if(n<=1) return 0;
int minbefore = prices[0];
for(int i=1;i<n;i++){
if(prices[i]-minbefore > maxProfit){
maxProfit = prices[i]-minbefore;
}
if(minbefore > prices[i])
minbefore = prices[i];
}
return maxProfit;
}
};
扩展:
- Best Time to Buy and Sell Stock II
支持多次交易,如果后一天的数值大于当天的数值,就把差值加入到最大收益中。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
int maxProfit = 0;
if(n<=1) return 0;
for(int i=0;i<n-1;i++){
if(prices[i+1]-prices[i]>0)
maxProfit += prices[i+1]-prices[i];
}
return maxProfit;
}
};
-
Best Time to Buy and Sell Stock III
最多进行2次交易, -
Best Time to Buy and Sell Stock IV
-
Best Time to Buy and Sell Stock with Transaction Fee
-
Best Time to Buy and Sell Stock with Cool down
P307
64. 求1+2+…+n
略,看pdf
P310
65.不用加减乘除做加法
class Solution {
public:
int Add(int num1, int num2)
{ int tmp1,tmp2;
while(num2!=0){
tmp1 = num1^num2;
tmp2 = num1&num2;
tmp2 = tmp2<<1;
num1=tmp1;
num2=tmp2;
}
return num1;
}
};
P313
66.构建乘积数组
class Solution {
public:
vector<int> multiply(const vector<int>& A) {
int n = A.size();
vector<int> res;
if(n==0) return res;
int tmp = 1;
for(int i=0;i<n;i++){
res.push_back(tmp);
tmp = tmp * A[i];
}
tmp = 1;
for(int i=n-1;i>=0;i--){
res[i] = res[i]*tmp;
tmp = tmp * A[i];
}
return res;
}
};
P318
67. 把字符串转换成整数
class Solution {
public:
int state = 1; // 1代表不合法,0代表合法
int StrToInt(string str) {
long long number=0;
if(str=="") {
return 0;
}else{
int minus = 1;
int start = 0;
if(str[0]=='+'){
start++;
}else if(str[0]=='-'){
minus = -1;
start++;
}
if(start < str.length()){
for(int i=start;i<str.length();i++){
if(str[i]>='0' && str[i]<='9'){
number = number*10+(str[i]-'0')*minus;
if( (minus==1 && number > 0x7FFFFFFF) || (minus==-1 && number < (signed int)0x80000000))
return 0;
}else{
return 0;
}
}
state = 0;
return (int)number;
}else{
return 0;
}
}
}
};
P326
68.树中两个节点的最低公共祖先