1. LC283.移动零
题目链接
解法一:O(n^2)(不用看了,第一遍尝试的解法,时间复杂度太高)
依次往后遍历,每遇到0,后面的数就挨个往前移一个,fast指向0应该移到末尾的位置,将fast处置0。
class Solution {
public void moveZeroes(int[] nums) {
int fast = nums.length - 1;
for (int i=0; i<fast; i++){
if (nums[i] == 0){
move(i, fast, nums);
fast--;
i--;
}
}
}
public void move(int slow, int fast, int[] nums){
for (int i=slow; i<fast; i++){
nums[i] = nums[i+1];
}
nums[fast] = 0;
}
}
解法二:O(n)
两个指针,fast,slow。
fast从0开始往后遍历,遇到不是0的数,就存到slow指针指向的地方,slow往前移一个。
相当于fast往前移动着,slow接着fast传过来的不为0的数据。
最后,slow停在末端0串的开头,于是从slow开始遍历到最后一个,全部置0。
class Solution {
public void moveZeroes(int[] nums) {
int slow = 0;
for (int fast=0; fast<nums.length; fast++){
if (nums[fast] != 0){
nums[slow] = nums[fast];
slow++;
}
}
while (slow < nums.length){
nums[slow] = 0;
slow++;
}
}
}
2. LC11.盛最多水的容器
题目链接
左右指针。
初始:左指针指向0,右指针指向最右边。计算面积。
然后开始向中间移动。
如果移动长边,则水的高度要么是原短边的高度,要么是新的长边移动后得到一个更短的短边的高度,再加上x轴距离也在缩小,所以容积必然更小。
如果移动短边,则短边移动后的高度有可能会变高,容积可能增大。
所以定义while循环,left<right。移动短边,不断向中间聚拢。
class Solution {
public int maxArea(int[] height) {
int left = 0;
int right = height.length - 1;
int max = 0;
int cur = 0;
while (left < right){
cur = (right - left) * Math.min(height[left], height[right]);
if (cur > max){
max = cur;
}
if (height[left] > height[right]){
right--;
}else{
left++;
}
}
return max;
}
}
3. LC42.接雨水
- 首先对于每个位置上能接的雨水量,都取决于这个位置的左边的最大值和右边的最大值。能接的雨水量为
min(leftMax, rightMax)
。如果height[i]
小于这个最大值,则可以接到雨水min-height[i]
- 左右双指针从两头往中间遍历。left从左往右移动,right从右往左移动。对于left来说,它的leftMax是真实的,因为是一步一步遍历到left得出来的最大值。所以如果leftMax < rightMax,之后的rightMax只可能比现在的rightMax更大,则left能接的雨水的值就能确定了:
leftMax-height[left]
- 对于right来说,它的rightMax是真实的,因为是一步一步从最右边遍历到right得出来的最大值。所以如果rightMax < leftMax,之后的leftMax只可能比现在的rightMax更大,则right能接的雨水的值就能确定了:
rightMax-height[right]
- 综上,左右指针分别从左数第二个和右数第二个向中间遍历,遍历过程中更新leftMax和rightMax。若leftMax < rightMax,left位置能接的雨水量确定,left右移。若rightMax < leftMax,right位置能接的雨水量确定,right左移。
最后一个我做的时候踩的坑!left和right在初始化的时候,是x坐标的数值。leftMax和rightMax在初始化的时候,是y坐标的数值。别忘了特殊情况,如果height的长度小于等于2,肯定是接不到雨水的,直接剔除掉这种情况,省的数组越界异常。
class Solution {
public int trap(int[] height) {
if (height.length <= 2){
return 0;
}
int left = 1;
int right = height.length - 2;
int leftMax = height[0];
int rightMax = height[height.length - 1];
int sum = 0;
while (left <= right){
if (leftMax < rightMax){
if (height[left] < leftMax){
sum += leftMax -height[left];
}else{
leftMax = height[left];
}
left++;
}else{
if (height[right] < rightMax){
sum += rightMax - height[right];
}else{
rightMax = height[right];
}
right--;
}
}
return sum;
}
}