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,否则……这里介绍数组初始化的几个方法:++中数组定义及初始化
一维数组:
- 静态 int array[100]; 定义了数组array,并未对数组进行初始化
- 静态 int array[100] = {1,2}; 定义并初始化了数组array
- 动态 int* array = new int[100]; delete []array; 分配了长度为100的数组array
- 动态 int* array = new int[100](1,2); delete []array; 为长度为100的数组array初始化前两个元素
二维数组:
- 静态 int array[10][10]; 定义了数组,并未初始化
- 静态 int array[10][10] = { {1,1} , {2,2} }; 数组初始化了array[0][0,1]及array[1][0,1]
- 动态 int (*array)[n] = new int[m][n]; delete []array;
- 动态 int** array = new int*[m]; for(i) array[i] = new int[n]; for(i) delete []array[i]; delete []array; 多次析构
- 动态 int* array = new int[m][n]; delete []array; 数组按行存储
初始化为0:
- 全局数组 int arr[10];
- 局部数组 int arr[10] = {};(数组长度固定) int *dp = new int[number+1]();(数组长度不固定)
- 指针 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();
}
};
本文深入解析了数组中数字出现次数、逆序对、只出现一次的数字等八大算法问题,通过C++实现,涵盖了哈希表、位运算、动态规划等多种解题策略。
1413

被折叠的 条评论
为什么被折叠?



