目录
1.移动0
2.复写0
3.快乐数
4.盛最多水的容器
5.有效三角形的个数
6.和为s的两个数字
7.三数之和
8.四数之和
1.移动0
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:输入: nums = [0]
输出: [0]
class Solution {
public void moveZeroes(int[] array) {
int index0=-1;
for (int i = 0; i < array.length; i++) {
if(array[i]!=0){
if(index0!=-1){//(还没初始化)如果第一个0还没出现,那就不管现在出现的非0的数字
//如果出现了那就交换这个数字和第一个出现0的位置
int temp=array[i];
array[i]=array[index0];
array[index0]=temp;
index0++;
}
}
else{//遍历到0,初始化第一个0出现的下标
if(index0==-1){
index0=i;
}
}
}
}
}
//目标就是让0全部放在末尾
2.复写0
给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。
注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。
示例 1:
输入:arr = [1,0,2,3,0,4,5,0]
输出:[1,0,0,2,3,0,0,4]
解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]
示例 2:输入:arr = [1,2,3]
输出:[1,2,3]
解释:调用函数后,输入的数组将被修改为:[1,2,3]
根据双指针的异地操作将他优化成原地操作。
变成原地的过程会发现,覆盖问题,根据“删除数组中值为val的元素”。
class Solution {
public void duplicateZeros(int[] arr) {
int cur=0,dest=-1,n=arr.length;
//1.找到最后一个需要腹泻的数字
while(cur<n){
if(arr[cur]==0) dest+=2;
else dest+=1;
if(dest>=n-1) break;
cur++;
}
//2.处理边界情况
if(dest==n){
arr[n-1]=0;
cur--;
dest-=2;
}
//3.从后向前完成复写
while(cur>=0){
if(arr[cur]!=0) {
arr[dest--]=arr[cur--];
}else{
arr[dest--]=0;
arr[dest--]=0;
cur--;
}
}
}
}
3.快乐数
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
示例 1: 输入:n = 19 输出:true 解释: 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1
class Solution {
public int bitSum(int n){
int sum=0;
while(n!=0){
int t=n%10;
sum+=t*t;
n/=10;
}
return sum;
}
public boolean isHappy(int n) {
int slow=n,fast=bitSum(n);
while(slow!=fast){
slow=bitSum(slow);
fast=bitSum(bitSum(fast));
}
return slow==1;
}
}
4.盛最多水的容器
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。class Solution { public int maxArea(int[] height) { int left=0,right=height.length-1,ret=0; while(left<right){ int v=Math.min(height[left],height[right])*(right-left); ret=Math.max(ret,v); //左右两个值中相对小的移动; if(height[left]<height[right]) left++; else right--; } return ret; } }
5.有效三角形的个数
给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。
示例 1:
输入: nums = [2,2,3,4]
输出: 3
解释:有效的组合是:
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3暴力解
class Solution { public int triangleNumber(int[] nums) { Arrays.sort(nums); if(nums.length<3){ return 0; } int count=0; for(int i=0;i<nums.length;i++){ for(int j=i+1;j<nums.length;j++){ for(int k=j+1;k<nums.length;k++){ if(nums[j]+nums[i]>nums[k]){ count++; } } } } return count; } }
class Solution { public int triangleNumber(int[] nums) { //利用单调性的双指针 //1.排序 Arrays.sort(nums); //2.利用双指针; int ret=0,n=nums.length; for(int i=n-1;i>=2;i--){//固定最大的数 //利用left,right指针统计符合要求的三元组的个数 int left=0,right=i-1; while(left<right){ if(nums[left]+nums[right]>nums[i]){ ret+=right-left; right--; }else{ left++; } } } return ret; } }
6.和为s的两个数字
class Solution {
public int[] twoSum(int[] nums, int target) {
int i = 0, j = nums.length - 1;
while(i < j) {
int s = nums[i] + nums[j];
if(s < target) i++;
else if(s > target) j--;
else return new int[] { nums[i], nums[j] };
}
return new int[0];
}
}
7.三数之和
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ret=new ArrayList<>();
Arrays.sort(nums);
int n=nums.length;
for(int i=0;i<n;){
if(nums[i]>0) break;//小优化
int left=i+1,right=n-1,target=-nums[i];
while(left<right){
int sum=nums[left]+nums[right];
if(sum>target) right--;
else if(sum<target) left++;
else{
ret.add(new ArrayList<Integer>(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++;
while(i<n&&nums[i]==nums[i-1]) i++;
}
return ret;
}
}
8.四数之和
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
排序+双指针
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ret=new ArrayList<>();
Arrays.sort(nums);
int n=nums.length;
for(int i=0;i<nums.length;){
for(int j=i+1;j<nums.length;){
int left=j+1,right=n-1;
long aim=(long)target-nums[i]-nums[j];//最后看测试用例·然后改这里;
while(left<right){
int sum=nums[left]+nums[right];
if(sum>aim) right--;
else if(sum<aim) left++;
else{
// ret.add(new ArrayList<Integer>(Arrays.asList(nums[i],nums[j],nums[left++],nums[right--])));
ret.add(Arrays.asList(nums[i],nums[j],nums[left++],nums[right--]));
//这两种我看都是可以的
//去重1
while(left<right&&nums[left]==nums[left-1]) left++;
while(left<right&&nums[right]==nums[right+1]) right--;
}
}//去重2
j++;
while(j<n&&nums[j]==nums[j-1]) j++;
}
//去重3
i++;
while(i<n&&nums[i]==nums[i-1]) i++;
}
return ret;
}
}