剑指offer(41-68题)

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.树中两个节点的最低公共祖先

猜你喜欢

转载自blog.csdn.net/YQMind/article/details/83964259