刷题日常(移动零,盛最多水的容器,三数之和,无重复字符的最长子串)
移动零
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
俩种情况:
1.当nums[i]为0的时候 直接i++2.当nums[i]不为0的时候 此时 需要跟 nums[j]交换 因为nums[j]一直处于0的位置
并且j++,i++
class Solution {
public void moveZeroes(int[] nums) {
int i = 0 , j = 0;
while( i < nums.length) {
if(nums[i] == 0) {
i++;
} else {
swap(nums,i++,j++);
}
}
}
public void swap(int[] nums,int i ,int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
盛最多水的容器
给定一个长度为 n
的整数数组 height
。有 n
条垂线,第 i
条线的两个端点是 (i, 0)
和 (i, height[i])
。
找出其中的两条线,使得它们与 x
轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
装多少水是由最短边决定的,为什么最短边移动,是因为如果长边移动,那么装的水可能会少,(因为由最短边决定,无论你长边移动后高度增加或者减少,都只能是装水量变少。)不可能会多。而如果移动最短边,那么有可能能够装更多的水。
class Solution {
public int maxArea(int[] height) {
int left = 0 ,right = height.length-1, ret=0;
while(left<right) {
int m = Math.min(height[left],height[right])*(right-left);
ret = Math.max(m,ret);
if(height[left] < height[right]) {
left++;
} else{
right--;
}
}
return ret;
}
}
三数之和
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组
1.先进行排序 要找到三个数字和为0的一组数组 所有先给数组排序
如果数组首元素大于0 可以直接返回空
2.固定其中某个数字,然后在剩余的数组里面找到和为 -nums[i]的数组 ,就说明找到了
3.细节处理 : 因为数组中可能有重复的数字,所以我们要去“去重”,至于哪些要去重呢?
1)i 一定要去重,跳过重复元素,
2) left 和right 也要去重
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
// 递增
Arrays.sort(nums);
// 定义返回的结果
List<List<Integer>> ret = new ArrayList<>();
for (int i = 0; i < nums.length;) {
// 一个数为整数 不可能找到和为0的俩个数组 因为已经排序
if (nums[i] > 0) {
break;
}
// 定义在i后面的数组区间寻找
int left = i + 1, right = nums.length - 1;
// 找-nums[i]
int k = -nums[i];
// 开始寻找和为k的一对数组
while (left < right) {
if (nums[left] + nums[right] < k) {
left++;
} else if (nums[left] + nums[right] > k) {
right--;
} else {
// 说明找到了
ret.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right])));
left++;
right--;
// 去重
while (left < right && nums[left] == nums[left - 1]) {
left++;
}
while (left < right && nums[right] == nums[right + 1]) {
right--;
}
}
}
i++;
// 去重i
while (i < nums.length && nums[i] == nums[i - 1] ) {
i++;
}
}
return ret;
}
}
无重复字符的最长子串
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串的长度
题目分析:
暴力解法:哈希表+遍历
明显这样写效率低,容易超时
使用一个哈希表 ,L记录无重复字符最长子串的起始 R记录无重复字符最长子串的尾巴
用R去遍历整个数组,每次遍历前判断哈希表是否存在此字符,
如果hash内不存在 直接添加到hash表中,并且计算此时的长度,不断更新最长的
如果hash内存在 重点来了:
一直判断L上的位置是否为存在的字符,如果不是,则一直弹出 直到没有重复的字符 ,然后加入到hash表中。计算此时的长度
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> hash = new HashSet<>();
int right = 0,left = 0 , len=0;
for(right = 0;right<s.length();right++) {
char ch = s.charAt(right);
while(left < right && hash.contains(ch)) {
hash.remove(s.charAt(left));
left++;
}
hash.add(ch);
len = Math.max(len,right-left+1);
}
return len;
}
}
24-25
结语: 写博客不仅仅是为了分享学习经历,同时这也有利于我巩固知识点,总结该知识点,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进。同时也希望读者们不吝啬你们的点赞+收藏+关注,你们的鼓励是我创作的最大动力!