NO.1
** LeetCode-283(移动零)**
题目相关描述请点链接
基础写法:
class Solution {
public void moveZeroes(int[] nums) {
if(nums==null) {
return;
}
//设置指针i j
//遍历nums[i] 当nums[i]!=0 即当值不为0时 nums[j]=nums[i];j++;
int j = 0;
for(int i=0;i<nums.length;++i) {
if(nums[i]!=0) {
nums[j++] = nums[i];
}
}
//可以使i j指针同时向右移 只有当nums[i]!=0 j才移动 造成j指针是慢的一方 所有0遍历完后 数组中>j&&<nums.length的全放0即可
for(int i=j;i<nums.length;++i) {
nums[i] = 0;
}
}
}
优化
class Solution {
public void moveZeroes(int[] nums) {
if (nums == null || nums.length == 0) {
return;
}
//优化之处在于只进行一次循环,边循环的同时移动i j指针 当数非0时赋给nums[j]
int j = 0;
for (int i = 0; i < nums.length; i ++){
//nums[i]==0 时不需要进行操作 即指针j不需要移动 造成j为慢指针
if (nums[i] != 0) {
if (i != j) { //将数值只有一个元素时的情况考虑进去
nums[j] = nums[i];
nums[i] = 0;
}
j ++;
}
}
}
}
精简
public void moveZeroes(int[] nums) {
if (nums == null || nums.length == 0) return;
int insertPos = 0;//慢指针
for (int num: nums) {
if (num != 0) nums[insertPos++] = num;
}
while (insertPos < nums.length) {
nums[insertPos++] = 0;
}
}
class Solution {
public int maxArea(int[] height) {
//主题思路:利用左右指针 小的一方移动 迭代计算出最大体积
int l=0,r=height.length-1;
int ans=0;
while(l<r){
//短板效应 面积是底(r-l) 高是左右指针对应数值较小的一方
int area=Math.min(height[l],height[r])*(r-l);
//每次计算记录最优值
ans=Math.max(ans,area);
if(height[l]<height[r])
{
++l;
}else{
--r;
}
}
return ans;
}
}
class Solution {
//题目抽象出为斐波拉数列模型 f(n)=f(n-1)+f(n-2)
public int climbStairs(int n) {
if(n==0||n==1||n==2){
return n;
}
int [] a=new int[n+1];
a[0]=0;
a[1]=1;
a[2]=2;
for(int i=3;i<=n;i++){
a[i]=a[i-1]+a[i-2];
}
return a[n];
}
}
class Solution {
public int[] twoSum(int[] nums, int target) {
//巧妙利用哈希的一键对应一值
Map<Integer,Integer> map =new HashMap<>();
for(int i=0;i<nums.length;i++){
int a=target-nums[i];
//两数之和=target 反过来即是target-一方=另一方
if(map.containsKey(a)){
//map中的containsKey(key)方法是判断该key在map中是否有key存在。如果存在则返回true。如果不存在则返回false。
return new int []{map.get(a),i};
}
map.put(nums[i],i);
}
throw new IllegalArgumentException("No two sum solution");
}
}
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);//排序处理 复杂度logn
List<List<Integer>> res = new ArrayList<>();
for(int k = 0; k < nums.length - 2; k++){//-2是为了留位置给i j双指针
if(nums[k] > 0) break;//k是固定在最左边的指针 排序后nums[k]最小>0显然不符合
if(k > 0 && nums[k] == nums[k - 1]) continue;//target值nums[k]如果等于上一次的值 那么已经得过正解 跳过此次循环
int i = k + 1, j = nums.length - 1;
while(i < j){
int sum = nums[k] + nums[i] + nums[j];
if(sum < 0){//sum<0意味着值为负 左指针需要右移增大数值
while(i < j && nums[i] == nums[++i]);
} else if (sum > 0) {//sum>0意味着值为正 右指针需要左移减小数值
while(i < j && nums[j] == nums[--j]);
} else {
res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));
while(i < j && nums[i] == nums[++i]);
while(i < j && nums[j] == nums[--j]);
}
}
}
return res;
}
}
class Solution {
public int[] plusOne(int[] digits) {
//最后一个数+1 当需要进位时则循环向前+1
//直到digits[i]!=0 返回数组
for(int i=digits.length-1;i>=0;i--){
digits[i]++;
digits[i]=digits[i]%10;
if(digits[i]!=0) return digits;
}
//特殊情况 例如当digits[]=9999
//则需要手动再扩大数组 将digits[0]=1
digits=new int [digits.length+1];
digits[0]=1;
return digits;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
if((head==null)||(head.next==null)){
return head;
}
//创建两个中间结点
ListNode first=head;
ListNode second=head.next;
//交换过后first.next=second.next
first.next=swapPairs(second.next);
//而second.next指向first
second.next=first;
return second;
}
}
class Solution {
public void rotate(int[] nums, int k) {
k=k%nums.length;
//巧妙利用反转
reserve(nums,0,nums.length-1);//整体反转
reserve(nums,0,k-1);//反转前K个
reserve(nums,k,nums.length-1);//反转后半段
}
public void reserve(int[] nums,int start,int end){
while(start<end){//不停反转从start到end的数
int temp;
temp=nums[start];
nums[start]=nums[end];
nums[end]=temp;
start++;
end--;
}
}
}
//递归
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null){
return l2;
}else if(l2==null){
return l1;
}else if(l1.val<l2.val){//当链表l1的值小于链表l2 则移动链表l1
l1.next=mergeTwoLists(l1.next,l2);
return l1;
}else{
l2.next=mergeTwoLists(l1,l2.next);
return l2;
}
}
}
//迭代
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode prehead=new ListNode(-1);//维护一个节点
ListNode prev=prehead;
while(l1!=null&&l2!=null){
//当两个链表不为空 则依次比较其中节点的大小
if(l1.val<l2.val){//当l1链表小 则将维护的链表指向l1,且l1往后移
prev.next=l1;
l1=l1.next;
}else{
prev.next=l2;
l2=l2.next;
}
prev=prev.next;//没获取一次 移动一次
}
prev.next=l1==null? l2:l1;
return prehead.next;
}
}
class Solution {
//双指针 从后往前
public void merge(int[] nums1, int m, int[] nums2, int n) {
// 三指针 指针一p1、nums1有效元素尾部;指针二p2、nums2尾部;指针三p3、最终数组尾部
// 当,p1>=0时,nums[p1],nums[p2]对比
int p1=m-1,p2=n-1,p3=m+n-1;
while(p2 >= 0){//因为是将nums2合并到nums1中 ,所以结束条件是p2--到零
if(p1 >= 0 && nums1[p1] > nums2[p2]){
nums1[p3--] = nums1[p1--];//nums[p1]大,将nums[p1]放入p3位置。p1--,p3--
} else {
nums1[p3--] = nums2[p2--];
//nums[p2]大于等于nums[p1],将nums[p2]放入p3位置。p2--,p3--
//当,p1<0时,将nums[p2]放入p3位置。p2--,p3--
}
}
}
}
//1.按列求
class Solution {
public int trap(int[] height) {
int sum = 0;
//最两端的列不用考虑,因为一定不会有水。所以下标从 1 到 length - 2
for (int i = 1; i < height.length - 1; i++) {
int max_left = 0;
//找出左边最高
for (int j = i - 1; j >= 0; j--) {
if (height[j] > max_left) {
max_left = height[j];
}
}
int max_right = 0;
//找出右边最高
for (int j = i + 1; j < height.length; j++) {
if (height[j] > max_right) {
max_right = height[j];
}
}
//找出两端较小的
int min = Math.min(max_left, max_right);
//只有较小的一段大于当前列的高度才会有水,其他情况不会有水
if (min > height[i]) {
sum = sum + (min - height[i]);
}
}
return sum;
}
}
//2.双指针
class Solution {
public int trap(int[] height) {
int left=0,right=height.length-1;
int ans=0;
int left_max=0,right_max=0;
while(left<right){
//当左柱子小于右柱子更新左边 当右柱子小于左柱子更新右边
if(height[left]<height[right]){
//当柱子大于左边记录的最大值则覆盖 小于最大值则有积水
if(height[left]>=left_max){
left_max=height[left];
}else{
ans+=(left_max-height[left]);
}
++left;
}else{
//当柱子大于右边记录的最大值覆盖 小于最大值则有积水
if(height[right]>=right_max){
right_max=height[right];
}else{
ans+=(right_max-height[right]);
}
--right;
}
}
return ans;
}
}
学习总结:
1.牢记过遍数的重要性,每日跟进学习刷题。
2.刷题时重点掌握最好的题解,多学习其他人的优秀代码,开阔自己的思维。
3.认真且自主的学习讲义所有内容,学会分析源代码。
4.学习的情况不是很理想,观看学习视频时不够集中,每日安排的时间质量不够好。还没有掌握自己的思维模式,需要学习更加优秀的总结方法。
(此文章为自己学习记录 没有详细的思路讲解)