菜鸡挑战五天刷完剑指offer day3-1

1.数字在排序数组中出现的次数

哈希表很简单,但是看LeetCode的回答,并不是很简单:

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        unordered_map<int , int> p;
        for(int i=0;i<data.size();i++){
            p[data[i]]++;
        }
        return p[k];
    }
};

leetcode中数组并不是有序的,且,需要返回重复的数字:

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
      unordered_set<int> p;
        for(int i : nums)
        {
            if(p.count(i) == 1) return i; // 假如hashset中已经有i了,说明重复了,返回i
            else p.insert(i);
        }
        return -1;
    }
};

所以在此贴一下指针的做法:

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
      sort(nums.begin(), nums.end());
      for(int i=0;i<nums.size()-1;i++){
          if(nums[i]==nums[i+1]){
              return nums[i];
          }
      }
      return -1;
    }
};

 

2.数组中的逆序对

类似于之前发布的排序中的归并方法。

class Solution {
public:
   int res=0;int n=1000000007;
    vector<int> temp;
    int InversePairs(vector<int> data) {
           temp = vector<int>(data.size(), 0);
        return mergesort(0, data.size() - 1,data);

    }
    int mergesort(int l,int r,vector<int>& nums){
      if (l >= r) return 0;
       int mid=(l+r)/2;
       
       mergesort(l,mid,nums);
       mergesort(mid+1,r,nums);
 
       int i=0;
       int p1=l;
       int p2=mid+1;
       while(p1<=mid && p2<=r){
           if(nums[p1]>nums[p2]){
          temp[i++]=nums[p2++];
          //只需要加这么两句
           res+=mid-p1+1;
               res%=n;
       }else{
        temp[i++]=nums[p1++];
        }
       }
       while(p1<=mid )temp[i++]=nums[p1++];
       while(p2<=r )temp[i++]=nums[p2++];
      //一定要复制到原数组中
       for (i = 0; i < r - l + 1; ++i) nums[l + i] = temp[i];
       return res;
       
    }

};

 

3.数组中只出现一次的数字

哈希表是个神奇的东西。

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
          unordered_map<int,int>p;
        vector<int> res;
        for(auto c:data)p[c]++;
        for(auto c:data){
            if(p[c]==1)
                res.push_back(c);
        }
        *num1=res[0];
        *num2=res[1];
    }
};

还有位运算的方法:

  • n^0 = n;
  • n^n = 0;
  • n^n^m = n^(n^m) 

若只有一个数字出现了一次:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
         int ret = 0;
        for (auto e: nums) ret ^= e;
        return ret;
    }
};

 

4.和为S的两个数字

在我的博客从2数之和到4数之和里写过,只需要随时更新一下最小乘积的数组。

class Solution {
public:
    vector<int> FindNumbersWithSum(vector<int> array,int sum) {
        int i=0,j=array.size()-1;
        int ans= INT_MAX;
        vector<int> res;
        vector<int> nums=array;
        while(i<j){
            if(nums[i]+nums[j]>sum)j--;
            else if(nums[i]+nums[j]<sum)i++;
            else {
                if(nums[i]*nums[j]<ans){
                    ans=nums[i]*nums[j];
                    res.clear();
                    res.push_back(nums[i]);
                    res.push_back(nums[j]);
                }
                i++;
            }
        }
        return res;
    }
};

 

5.构建乘积数组

先算左边,再算右边,两个相乘:

class Solution {
public:
    vector<int> multiply(const vector<int>& A) {
       vector<int> B(A.size(),1);
        if(A.empty())return vector<int>();
        for(int i=1;i<A.size();i++){
            B[i] = B[i-1] * A[i-1];
        }
        int temp=1;
        for(int j=A.size()-2; j>=0; j--){
            temp*=A[j+1];
            B[j]*=temp;
        }
        return B;
    }
};

 

6.机器人的运动范围

恩,这道题没有思路,我比较局限,以为是用动态规划,实际是用DFS和BFS做:

class Solution {
public:
    
    int movingCount(int threshold, int rows, int cols)
    {
     vector<vector<bool>> p(rows,vector<bool>(cols,false));
        return dfs(rows,cols,0,0,p,threshold);
    }
    
 //数位和
    int sum(int num){
        int sum= 0;
        while(num){
            sum+=num%10;
            num/=10;
        }
        return sum;
    }
    
//dfs
    int dfs(int rows, int cols, int i, int j, vector<vector<bool>>&p,int threshold){
        if(i<0||i>=rows||j<0||j>=cols||sum(i)+sum(j)>threshold||p[i][j]==true)
            return 0;
        p[i][j]=true;
        return 1+dfs(rows,cols,i-1,j,p,threshold)+dfs(rows,cols,i+1,j,p,threshold)+
               dfs(rows,cols,i,j-1,p,threshold)+dfs(rows,cols,i,j+1,p,threshold);
    }
};

 

7.剪绳子

还是挺懵逼的,多多理解吧。这里需要注意,1、2、3的返回值和dp数组中的值是不一样的,是因为若大于3,那么就不切分了:

class Solution {
public:
    int cutRope(int number) {
        int *dp = new int[number+1]();
        if(number==1)return 0;
        if(number==2)return 1;
        if(number==3)return 2;
        dp[1]=1;
        dp[2]=2;
        dp[3]=3;
       
         for(int i=4;i<=number;i++){
            for(int j=1;j<=i/2;j++){
                dp[i]=max(dp[i],dp[j]*dp[i-j]);
            }
        }

        return dp[number];
    }
};

同时,数组一定要初始化为0,否则……这里介绍数组初始化的几个方法:++中数组定义及初始化

一维数组:

  1. 静态 int array[100];   定义了数组array,并未对数组进行初始化
  2. 静态 int array[100] = {1,2};  定义并初始化了数组array
  3. 动态 int* array = new int[100];  delete []array;  分配了长度为100的数组array 
  4. 动态 int* array = new int[100](1,2);  delete []array; 为长度为100的数组array初始化前两个元素

二维数组:

  1. 静态 int array[10][10];  定义了数组,并未初始化
  2. 静态 int array[10][10] = { {1,1} , {2,2} };  数组初始化了array[0][0,1]及array[1][0,1]
  3. 动态 int (*array)[n] = new int[m][n]; delete []array;
  4. 动态 int** array = new int*[m]; for(i) array[i] = new int[n];  for(i) delete []array[i]; delete []array;    多次析构
  5. 动态 int* array = new int[m][n];  delete []array;      数组按行存储

初始化为0:

  1. 全局数组  int arr[10];
  2. 局部数组  int arr[10] = {};(数组长度固定)     int *dp = new int[number+1]();(数组长度不固定)
  3. 指针  int* arr = new int [10]; for (int i = 0; i < 10; i ++) arr[i] = 0;

 

8.包含min函数的栈

俩栈,一个辅助栈,数据进数据栈,辅助栈保存最小值。

class Solution {
public:
    stack<int> res,helper;
    void push(int value) {
        res.push(value);
        if(helper.empty() || value <= helper.top()){
        helper.push(value);
        }else{
            helper.push(helper.top());
        }
    }
    void pop() {
        res.pop();
        helper.pop();
    }
    int top() {
        return res.top();
    }
    int min() {
        return helper.top();
    }
};

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值