目录
五、611. 有效三角形的个数 - 力扣(LeetCode)
六、和为S的两个数字_牛客题霸_牛客网 (nowcoder.com)
七、LCR 007. 三数之和 - 力扣(LeetCode)
主要思想
数组下表充当指针
数组划分、数组分块
主要的思想,就是划分数组区间,只要是数组区间,或者某个区间,都可以尝试使用这种思想解决。
一、283. 移动零 - 力扣(LeetCode)
思路:
两个指针,一个指针往后遍历,把不是0的数字往前交换
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int j = -1;
for(int i = 0; i<nums.size();++i)
{
if(nums[i] != 0)
{
swap(nums[++j],nums[i]);
}
}
}
};
二、1089. 复写零 - 力扣(LeetCode)
思路:
因为0复写之后,数组需要向后移动一位;因此在移动之前,我们需要知道复写完成后,哪一个数据是数组最后位置,找到这个位置之后,就可以从该位置开始,从后往前遍历:不是0,往后移动,是0,后面往前两个位置都是0
class Solution {
public:
void duplicateZeros(vector<int>& arr) {
//双指针法
//从前往后移动,会覆盖数据
//考虑从后往前
///但是从后往前,不知道最后一个数据会a改成什么样子
//所以,第一步,先找到最后一个数据
int cur = 0,dest = -1, n = arr.size();
while(cur < n)
{
if(arr[cur])
{
dest++;
}
else
{
dest += 2;
}
if(dest >= n - 1)
break;
cur++;
}
if(dest == n)
{
arr[n-1] = 0;
cur--;
dest -= 2;
}
while(cur >= 0)
{
if(arr[cur])
{
arr[dest] = arr[cur];
dest--;
cur--;
}
else
{
arr[dest] = 0;
arr[dest - 1] = 0;
dest -= 2;
cur--;
}
}
}
};
三、202. 快乐数 - 力扣(LeetCode)
思路:
class Solution {
public:
int get_num( int n)
{
int t = 0;
int ret =0;
while(n)
{
t = n%10;
ret += t * t;
n /= 10;
}
return ret;
}
bool isHappy(int n) {
int slow = n;
int fast = get_num(n);
while(slow != fast)
{
slow = get_num(slow);
fast = get_num(get_num(fast));
}
return slow == 1;
}
};
四、11. 盛最多水的容器 - 力扣(LeetCode)
思路:
class Solution {
public:
int get_size(int x, int y)
{
return x * y;
}
int maxArea(vector<int>& height) {
int left = 0;
int right = height.size() -1 ;
int max = 0;
while(left != right)
{
int v = get_size(right-left, min(height[left],height[right]));
if(height[left] <= height[right])
left++;
else
right--;
max = std::max(v, max);
}
return max;
}
};
五、611. 有效三角形的个数 - 力扣(LeetCode)
思路:两边之和大于第三边。先对数据排序。再用指针找数据
class Solution {
public:
int triangleNumber(vector<int>& nums) {
int left = 0;
int dest = nums.size() - 1;
int right = dest - 1;
int cont = 0;
sort(nums.begin(),nums.end());
while(dest > 1)
{
while(left != right)
{
if(nums[left] + nums[right] > nums[dest])
{
cont += right - left;
--right;
}
else
{
++left;
}
}
--dest;
right = dest - 1;
left = 0;
}
return cont;
}
};
六、和为S的两个数字_牛客题霸_牛客网 (nowcoder.com)
思路:
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
int left = 0;
int right = array.size() - 1;
vector<int> ret;
while(left < right)
{
if(array[right] > sum)
{
--right;
}
else
{
if(array[left] + array[right] < sum)
{
++left;
}
else if(array[left] + array[right] > sum)
{
right--;
}
else
{
ret.push_back(array[left]);
ret.push_back(array[right]);
break;
}
}
}
return ret;
}
};
七、LCR 007. 三数之和 - 力扣(LeetCode)
思路:先排序,然后分成两个区间:右边的left-right区间,找到和i位置数相加等于0的配对
其实,就是上一题对两数之和的延展。单趟对i的配对,实际上就是找到数字相加等于i位置的相反数。单趟控制完毕,再控制整体,总共控制i-n次单躺操作
这个题目主要在于去重,单趟的去重,就是看left和right前后有没有出现重复;整体的去重,就是对重复的i元素进行去重。用while去重
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ret;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); ++i) {
// 对i查重
if (i > 0 && nums[i] == nums[i - 1])
continue;
int left = i + 1;
int right = nums.size() - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0) {
ret.push_back({nums[i], nums[left], nums[right]});
// 跳过重复元素
while (left < right && nums[left] == nums[left + 1])
left++;
while (left < right && nums[right] == nums[right - 1])
right--;
left++;
right--;
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return ret;
}
};
八、18. 四数之和 - 力扣(LeetCode)
思路:四数之和,就是三个数之和再加上第四个数字,可以划分区间;三数之和,就是两个数字加上第三个数字,也可以划分区间。划分如下图所示:(同时要处理去重的问题)
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ret;
sort(nums.begin(),nums.end());
int n = nums.size();
for(int i = 0; i < n - 3;++i)
{
if (i > 0 && nums[i] == nums[i - 1]) continue;
for(int j = i + 1;j<n - 2; ++j)
{
if (j > i + 1 && nums[j] == nums[j - 1]) continue; // 去重
int left = j +1;
int right = n - 1;
while(left < right)
{
long long sum = static_cast<long long>(nums[i]) + nums[j] + nums[left] + nums[right];
if(sum > target)
--right;
else if(sum < target)
++left;
else
{
ret.push_back({nums[i] , nums[j] , nums[left] , nums[right]});
++left;
--right;
//对数据去重
while(left < right && nums[left] == nums[left - 1]) ++left;
while(left < right && nums[right] == nums[right + 1]) --right;
}
}
}
}
return ret;
}
};