剑指offer 53~66

本文探讨了五种算法问题:在排序数组中查找数字、确定0-1区间缺失数字、二叉搜索树的第k大节点、二叉树深度及平衡判断、以及数组中数字出现次数。通过Solution类展示了C++解决方案,涉及数据结构、搜索算法、排序和树的遍历技巧。
摘要由CSDN通过智能技术生成
53 - I. 在排序数组中查找数字 I
class Solution {
public:
    int ans = 0;
    void countsum(vector<int>& nums, int left,
    int right, int& target){
    if(left > right) return;
        int mid = left + (right - left)/2;
        if(nums[mid] == target){
            ans++;
        }
        countsum(nums, left, mid - 1, target);
        countsum(nums, mid + 1, right,target);
        }
    int search(vector<int>& nums, int target) {
    countsum(nums, 0, nums.size() - 1, target);
    return ans;
    }
};
53 - II. 0~n-1中缺失的数字
class Solution {
public:
    int missingNumber(vector<int>& nums) {
     for(int i=0;i<nums.size();i++){
         if(nums[i]!=i)  return i;
     }
     return nums.size();
    }
};
54. 二叉搜索树的第k大节点
class Solution {
public:
   //二叉搜索树,中序遍历好像是有序的
    int num=0,ans=0; 
    int kthLargest(TreeNode* root, int k) {
         buid(root,k);
         return ans;
    }
    void buid(TreeNode* root, int k){
        if(root->right!=nullptr) buid(root->right,k);
        if(k==++num)  {ans=root->val;return;}
        if(root->left!=nullptr) buid(root->left,k);
    }
};
55 - I. 二叉树的深度
class Solution {
public:
    int maxDepth(TreeNode* root) {
      if(root==nullptr)  return 0;
      int left = maxDepth(root->left);
      int right = maxDepth(root->right);
      return left>right?left+1:right+1;
    }
};
55 - II. 平衡二叉树
class Solution {
public:
    bool isBalanced(TreeNode* root) {
        if(root==nullptr)  return true;
        else if(abs(deep(root->left)-deep(root->right))>1) return false;
        return isBalanced(root->left)&&isBalanced(root->right);
    }
    int deep(TreeNode* root){
        if(!root) return 0;
        return 1+max(deep(root->left),deep(root->right));
    }
};
56 - I. 数组中数字出现的次数
class Solution {
public: 
    //这题直接抄的,直接记吧,,,我有点没理解,,等写完在理解出单篇
    vector<int> singleNumbers(vector<int>& nums) {
     int v= 0;
     for(int i:nums){v^=i;}
     int low_bit=v&(-v);
     int a=0,b=0;
     for(int n:nums){
         if(n&low_bit){
             a^=n;
         }else{
             b^=n;
         }
     }
     return (a,b);
    }
};
56 - II. 数组中数字出现的次数 II
//今天咋回事咋没思路呀。。。。。
class Solution {
public:
    int singleNumber(vector<int>& nums) {
    unordered_map<int, int> mp;
    for(int i:nums)  mp[i]++;
    for(auto item:mp)  
         if(item.second == 1)
            return item.first;
    return -1;
    }
};
和为s的两个数字
class Solution {
public:
   //双指针,一个从前找一个从后找。。。
    vector<int> twoSum(vector<int>& nums, int target) {
     int n = nums.size();
     int left=0,right = n-1;
     while(left<right){
         int sum = nums[left]+nums[right];
         if(sum==target)  return {nums[left],nums[right]};
         else if(sum >target)  right -=1;
         else left+=1;
     }
     return {};
    }
};
57 - II. 和为s的连续正数序列
class Solution {
public:
    //连续。。就是n=(l+r)*(r-l)/2  双指针
    vector<vector<int>> findContinuousSequence(int target) {
    vector<vector<int>>  res;
    int left = 1,right = 2;
    while(left<right){
        vector<int> temp;
        int sum = (left+right)*(right-left+1)/2;
        if(sum<target) right+=1;
        else if(sum>target) left+=1;
        else {
            for(int i=left;i<=right;i++)
                temp.push_back(i);
            res.push_back(temp);
            left+=1;
            right+=1;
        }
    }
    return res;
    }
};
58 - I. 翻转单词顺序
class Solution {
public:
    string reverseWords(string s) {
    string res="",temp;
    stringstream ss(s);   //这是流操作
    while(ss>>temp){
        res = temp+" "+res;
    }
    res.pop_back();
    return res;
    }
};
58 - II. 左旋转字符串
class Solution {
public:
   //这不就是字符切割重装吗???
    string reverseLeftWords(string s, int n) {
     return s.substr(n) + s.substr(0,n);
    }
};
Offer 59 - I. 滑动窗口的最大值
class Solution {
public:
    //滑动窗口只需要遍历相加一次,,用队列
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
    int n = nums.size() ;
        deque<int> dq ;
        vector<int> res ;

        if (nums.size() == 0)
            return res ;
    
        for (int i = 0 ; i < n ; ++i) {
            while (!dq.empty() && i - dq.front() + 1 > k) {
                dq.pop_front() ;
            }
            while (!dq.empty() && nums[dq.back()] <= nums[i]) {
                dq.pop_back() ;
            }
            dq.push_back(i) ;
            if (i >= k - 1)
                res.push_back(nums[dq.front()]) ;
        }
        return res ;
    }
};
59 - II. 队列的最大值
class MaxQueue {
public:
   //和两个栈实现最小获取一样的思路,这个就是两个队列实现最大
   queue<int> que;
   deque<int> dque;
    MaxQueue() {

    }
    
    int max_value() {
        return que.empty()?-1:dque.front();
    }
    
    void push_back(int value) {
     que.push(value);
     while(!dque.empty() && dque.back()<value)
             dque.pop_back();
     dque.push_back(value);
    }
    
    int pop_front() {
    if(que.empty())  return -1;
    int t = que.front();
    que.pop();
    if(t==dque.front())   dque.pop_front();
    return t;
    }
};
60. n个骰子的点数
class Solution {
public:
    //num 1 2 3 4 5 6
    //      2 3 4 5 6 7 8 9 10 11 12
    //dp  1 1 1 1 1 1   6
    //    0 1 2 3 4 5 6 5 4  3  2  1  36     
    //每次少一个数字且添加6个数字。。草这他喵是dp,总共右6^n种
    //dp[i][j] +=dp[i-1][j-k]; 
    vector<double> dicesProbability(int n) {
    vector<vector<int>> dp(n+1,vector<int>(n*6+1,0));
    
    for(int i=1;i<=6;i++)   dp[1][i] = 1;

    for(int i=2;i<=n;i++){
        for(int j=i;j<=n*6;j++){
           for(int k=1;k<=6;k++){
              if(j-k>=0)  dp[i][j] +=dp[i-1][j-k]; 
            }
        }
    }
    vector<double> ans;

    for(int i=n;i<=n*6;i++){
        ans.push_back(dp[n][i]*1.0/pow(6,n));
    }
    return ans;
    }
};
61. 扑克牌中的顺子
class Solution {
public:
    bool isStraight(vector<int>& nums) {
    int n = nums.size();
    sort(nums.begin(),nums.end());
    int k = 0;
    unordered_map<int, int> mp;
    for(int i=0;i<n;i++){
        if(nums[i]==0) k++;
        if(++mp[nums[i]]>1&&nums[i]!=0)  return false;
    }
    return nums[n-1]-nums[k] <=4;
    }
};
62. 圆圈中最后剩下的数字
class Solution {
public:
    int lastRemaining(int n, int m) {
    int last=0;
    for(int i=2;i<=n;i++)  last=(last+m)%i;

    return last;
    }
};
63. 股票的最大利润
class Solution {
public:
//维护一个最小的值就行
    int maxProfit(vector<int>& prices) {
     int min=prices[0];
     int ans=0;
     for(int i=0;i<prices.size();i++){
         if(prices[i]<min)  min=prices[i];
         ans = max(ans,prices[i]-min);
     }
     return ans;
    }
};
64. 求1+2+…+n
class Solution {
public:
   //???????你在为难我
   //(n+1)n/2 = (n^2+n)/2
    int sumNums(int n) {
     return int(pow(n,2)+n)>>1;
    }
};
65. 不用加减乘除做加法
class Solution {
public:
   //位运算..
   // 1~0001 3~0011
   //大佬的口诀。。。异或保留,与进位, 与为空时就返回,自己没想到思路学到了。。。
    int add(int a, int b) {
    while(b!=0){
       int tmp=a^b;
        b=((unsigned int)(a&b)<<1);
        a=tmp;
    }
    return a;
    }
};
66. 构建乘积数组
class Solution {
public:
    //b里面是除了a[i]的其余的乘积。
    vector<int> constructArr(vector<int>& a) {
     int n = a.size();
     vector<int> ans(n,0);
     int temp=1;
     for(int i=0;i<n;i++){
         ans[i] = temp;
         temp *=a[i];
     }
     temp = 1;
     for(int i=n-1;i>=0;i--){
         ans[i]*=temp;
         temp*=a[i];
     }
     return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值