LeetCode-数据结构一
217-存在重复元素
思路1:暴力法:利用二重循环进行两个数的比较,相同则返回true,遍历完毕不相同则返回false
思路2:利用set的自动去重功能进行判断
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
set<int> s;
for(auto &it:nums)
{
int num = s.size();
s.insert(it);
if(num==s.size())
return true;
}
return false;
}
};
思路3:利用排序判断相邻的两个数是否相同
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
sort(nums.begin(), nums.end());
for(int i=0;i<nums.size()-1;i++)
{
if(nums[i]==nums[i+1])
{
return true;
}
}
return false;
}
};
思路4:利用hashmap进行重复的判断
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
map<int, int> m;
for(auto &it:nums)
{
if(m.find(it)==m.end())
{
m[it] = 1;
}
else
{
m[it]++;
if(m[it]>=2)
{
return true;
}
}
}
return false;
}
};
总结:巧妙利用数据结构的特性进行数据的操作
53-最大子数组和
这里注意到子数组是求连续最大和
思路1:贪心双指针法
贪心——考虑到最大和,我们不希望引入负数,但是为了保证连续且最大,所以如果当前数字加入不使得sum变为负数则可以加入,否则舍弃,重新计数
这里需要考虑最终结果为负数的情况,所以需要利用flag进行判断,能否找到第一个正数
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int ans = -INT_MAX;
int flag = 0;
int sum = -INT_MAX;
for(auto &i:nums)
{
//寻找第一个正数,否则在负数中找最大
if(flag==0)
{
if(i>=0)
{
sum = 0;
sum += i;
flag = 1;
}
else
ans = max(i, ans);
continue;
}
ans = max(sum, ans);
//正数则直接加上
if(i>=0)
sum+=i;
else//否则判断是否使sum小于0,不小于则加上,否则重新算
{
if(sum+i<=0)
sum = 0;
else
sum += i;
}
}
ans = max(sum, ans);
return ans;
}
}
思路2:动态规划
连续子序列
定义子问题——定义状态
对于[1, 2, -2, 3]:
子问题1:含1的连续子数组最大和是多少?
子问题2:含2的连续子数组最大和是多少?
子问题3:含-2的连续子数组最大和是多少?
子问题4:含3的连续子数组最大和是多少?
注意到子问题可能会有交集,我们需要对子问题进行细化:
子问题1:结尾为1的连续子数组最大和是多少?
子问题2:结尾为2的连续子数组最大和是多少?
子问题3:结尾为-2的连续子数组最大和是多少?
子问题4:结尾为3的连续子数组最大和是多少?
则可以按照动态规划题解的方法将:状态定义、状态转移方程,初始化都写出
arr[i]:表示nums[i]结尾的连续子数组的最大和
由于nums[i]一定会取,则我们需要判断我们是否需要前面的“最大连续前缀和”则
需要比较max{arr[i-1]+nums[i], nums[i]}
跟贪心的想法类似,当前面的和对当前没有贡献时,则舍去仅保留当前
则有
arr[i] = max{arr[i-1]+nums[i], nums[i]}
初始化:第一个数必定是以第一个数结尾,则arr[0] = nums[0]
最后考虑到一维的数组可以进行空间优化,进行数组压缩
仅利用一个变量来保存前一个状态即可:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int ans = nums[0];//初始化
int pre = 0;
for(auto &i:nums)
{
pre = max(pre+i, i);//状态转移方程
ans = max(ans, pre);//每次需要进行最大和的判断
}
return ans;
}
};
1-两数之和
在HOT100中思路一致,利用unordered_map存储对应元素的值和位置,通过target-nums[i]得到应该配对的数,在map中查找,找到则返回两数对应的位置,否则将nums[i]添加入map中
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//需要注意使用的是unordered map
unordered_map<int, int> hashmap;
for(int i=0;i<nums.size();i++)
{
int x = nums[i];
auto it = hashmap.find(target-x);
if(it!=hashmap.end())
{
return {it->second, i};
}
else
{
hashmap[x] = i;
}
}
return {};
}
};
88-合并两个有序数组
思路:利用归并排序的思路,对于两个有序的数组,利用辅助数组vector将其合并,最后将vector复制到nums1中
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
vector<int> ans;
int s1, s2;
s1 = s2 = 0;
while(s1<m&&s2<n)
{
if(nums1[s1]<=nums2[s2])
{
ans.push_back(nums1[s1]);
s1++;
}
else
{
ans.push_back(nums2[s2]);
s2++;
}
}
while(s1<m)
ans.push_back(nums1[s1++]);
while(s2<n)
ans.push_back(nums2[s2++]);
nums1.clear();
for(auto &it:ans)
{
nums1.push_back(it);
}
}
};
需要注意两个数组长度不一致时需要将长数组中没有进行比较的元素进行补充