数组

  1. 要求数组原地改变,用快慢指针。快指针是当前遍历的位置,慢指针是处理之后数组位置,数组长度有慢指针决定。
    推算一遍example,确定逻辑。
26. Remove Duplicates from Sorted Array
Example 1:
Given nums = [1,1,2],
Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
It doesn't matter what you leave beyond the returned length.
 class Solution {
 public:
	 int removeElement(vector<int> nums, int val) {
		 if (nums.size() == 0) return 0;
		 int low = 0, fast = 0;
		 while (fast < nums.size())
		 {
			 if (nums[fast] == nums[low])  fast++; //因为给low位置赋值,suoyigen num[low]比较。
			 else nums[++low] = nums[fast++];
		 }
		 return low+1;
	 }
 };

对数组去重最好用新数组索引和旧数组索引。

27. Remove Duplicates from Sorted Array II
重复元素至多出现n次。
Given nums = [1,1,1,2,2,3], n=2
Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively.
It doesn't matter what you leave beyond the returned length.
 class Solution {
 public:
	 int removeDuplicates(vector<int>& nums, int bwt ) {
		 if (nums.size() <= 1) return nums.size();
		 int pre = bwt;
		 for (int post = bwt; post < nums.size(); post++)
		 {
			 if (nums[post] != nums[pre - bwt]) nums[pre++] = nums[post];
		 }
		 return pre;
	 }
 };

变化前后的两数组如果存在变化快和变化慢的指针,那就用两个指针来处理。
56.Merge Intervals在合并区间时,设定[low, high]为合并后的边界。low缓慢变化,high通过判断区间是否相交变化快速,在快变量不变化的时候给新数组添加元素

 Example 1:
Input: [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
class Solution {
 public:
	 vector<vector<int>> merge(vector<vector<int>> intervals) {
		 if (intervals.empty()) return {};
		 vector<vector<int>> res;
		 sort(intervals.begin(), intervals.end(), cmp);

		 int low = intervals[0][0], high = intervals[0][1];//记录当前合并后的区间
		 for (int i = 1; i < intervals.size(); i++)
		 {//合并后区间和当前区间比较,判断有交集的条件
			 if (high >= intervals[i][0]) high = max(intervals[i][1], high);
			 else
			 {
				 res.push_back({ low, high });
				 low = intervals[i][0];
				 high = intervals[i][1];
			 }
		 }
		 res.push_back({ low, high });
		 return res;
	 }
	 static bool cmp(vector<int> &a, vector<int> &b)
	 {
		 return a[0] < b[0];
	 }
 };
27. Remove Element去掉数组中指定元素。
Example 1:

Given nums = [3,2,2,3], val = 3,

Your function should return length = 2, with the first two elements of nums being 2.

It doesn't matter what you leave beyond the returned length.
class Solution {
 public:
	 int removeElement(vector<int>& nums, int val) {
		 if (nums.size() == 0) return 0;
		 int low = 0, fast = 0;
		 while (fast < nums.size())
		 {
			 if (nums[fast] == val)  fast++;
			 else nums[low++] = nums[fast++];
		 }
		 return low;
	 }
 };
  1. 二分查找
    二分查找失败一定是high = low-1也即arr[high]<tar<arr[low],这时target在数组中的插入位置正好是low。
35. Search Insert Positio查找成功返回位置,失败返回插入位置。
Example 1:

Input: [1,3,5,6], 5
Output: 2
class Solution {
 public:
	 int searchInsert(vector<int>& nums, int target) {
		 if (nums.empty()) return 0;
		 int low = 0, high = nums.size() - 1;
		 while (low <= high)
		 {
			 int mid = (low + high) / 2;
			 if (nums[mid] < target) low = mid + 1;
			 else if (nums[mid] > target) high = mid - 1;
			 else return mid;
		 }
		 return low;
	 }
 };
  1. DFS 去重
    使用dfs穷举数组所有元素的排列情况,要不能出现重复项,重复来源于:第一中后面的元素去结合前面的元素,如[1,2],排列方式会[1,2], [2,1],这种设置start位置,只结合start及后面的元素;第二种,数组中含有重复项,不同的组合中重复项会造成组合的重复,如[1,1,7]–>[1,7]第一个1, [1,7]第二个1,同一for循环中如果当前元素和上一元素相同就不排列。注意同一递归层的for循环里是创造不同组合的;递归每一层是创造同一 组合的不同元素的。
    但是注意任何去重之前先排序。

3.1 在4-sum之后的无限项求和,求出和为target的所有元素组合。

4. Combination Sum II
Example 1:
Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]
 class Solution {
 public:
	 vector<vector<int>> combinationSum(vector<int> candidates, int target) {
		 vector<vector<int>> res;
		 if (candidates.empty())
			 return res;

		 sort(candidates.begin(), candidates.end());
		 core(res, {}, candidates, 0, target, 0);
		 return res;
	 }

	 void core(vector<vector<int>> &res, vector<int> out, vector<int> candidates, int cur, int target, int start)
	 {
		 if (cur == target)
		 {
			 res.push_back(out);
			 return;
		 }
		 if (cur > target) return;

		 for (int i = start; i < candidates.size(); i++)
		 {
			 if (i > start && candidates[i] == candidates[i - 1]) continue;
			 out.push_back(candidates[i]);
			 core(res, out, candidates, cur + candidates[i], target, i+1);
			 out.pop_back();
		 }
	 }
 };

3.2 90. Subsets II求数组的所有子集,去重复项情况同前。

Input: [1,2,2]
Output:
[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]
 class Solution {
 public:
 public:
	 vector<vector<int>> subsetsWithDup(vector<int>& nums) {
		 vector<vector<int>> res = { {} };
		 if (nums.empty()) return res;

		 sort(nums.begin(), nums.end());
		 dfs(res, nums, {}, 0);
		 return res;
	 }
	 void dfs(vector<vector<int>>& res, vector<int>& nums, vector<int> out, int start)
	 {
		 if (out.size()) res.push_back(out);

		 for (int i = start; i < nums.size(); i++)
		 {
			 if (i > start && nums[i] == nums[i - 1]) continue;
			 out.push_back(nums[i]);
			 dfs(res, nums, out, i + 1);
			 out.pop_back();
		 }
	 }
 };
  1. DFS注意两点:终止条件和约束条件(比如为了去重的约束条件),以及使用for循环还是类似迷宫的单步递归,取决于每次有几种可能性(即递归层数)。
    78.Subsets 穷举数列所有子集,包括空集。这里注意终止条件,不能用return否则无法想下递归。
Input: nums = [1,2,3]
Output:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

 class Solution {
 public:
	 vector<vector<int>> subsets(vector<int>& nums) {
		 vector<vector<int>> res{ {} };
		 if (nums.empty())
			 return res;
		 dfs(res, nums, {}, 0);
		 return res;
	 }
	 void dfs(vector<vector<int>> &res, vector<int>& nums, vector<int> out, int start)
	 {
		 if (out.size())
		 {
			 res.push_back(out);
			 //return;
		 }
		 for (int i = start; i < nums.size(); i++)
		 {
			 out.push_back(nums[i]);
			 dfs(res, nums, out, i + 1); //当start>= nums.size()不用额外添加终止判断,不进入for就可以了。
			 out.pop_back();
		 }
	 }
 };

3.3 避免string.substr(s,k)时k大于字符串长度,出现重复现象。因为k大于剩余长度和k等于剩余长度结果是一样的。

93. Restore IP Addresses
分割字符串,要求每段字符串符合要求。递归约束条件:
1. 小于等于255,而且不能有前导0.
2. 切出4段字符串后,正好切到结尾。 
class Solution {
public:
	vector<string> restoreIpAddresses(string s) {
		vector<string> res;
		core(res, {}, s, 0);
		return res;
	}

	void core(vector<string>& res, vector<string> ip, string s, int cut)
	{
		if (ip.size()==4 && cut>s.length()-1) {//切出4段字符串后,正好切到结尾。 
			string addr = ip[0] + "." + ip[1] + "." + ip[2] + "." + ip[3];
			res.push_back(addr);
			return;
		}
		if (ip.size() >= 4) return;
		
		for (int i = 1; i <= 3; i++)
		{
			if (i > s.length() - cut) break;//防止重复出现。
			string a = s.substr(cut, i);
			if (atoi(a.c_str()) > 255 || (a[0] == '0'&&a.length() > 1)) //约束
			   continue;
			ip.push_back(a);
			core(res, ip, s, cut + i);
			ip.pop_back();
		}
	}
};
  1. 最大和子数组
    最大和子数组, 要求子数组连续,求出最大和。用dp来做。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值