leedcode刷题手记

Day1

27.移除数组

题目:移除数组

首先想到非常丑陋的循环遍历的方法

class Solution {
    public int removeElement(int[] nums, int val) {
       int len=nums.length;
       for(int i=0;i<len;i++)
       {
           if(nums[i]==val)
           {
               for(int j=i+1;j<len;j++)
               {
                   nums[i]=nums[j];
               }
               len--;
               i--;
           }
       }
       return len;
    }
}

以上需要注意两点:1循环边界的问题:len=len-1;2当i个值找到目标值时记得在删除后更新i
问题:内存开销太大

一些改进:快慢指针

核心思想:当找到对应的nums[i]==val时,快指针指向下一个位置,但是慢指针不变,以便于在查找过程中用快指针的值替代慢指针指向的值。O(n)解决。
快指针:获取新数组元素
慢指针:更新位置
重点:由快指针承担对比工作
边界:直接输出slow就行,因为从0开始
类似题目:26删除有序数组重复项
思路:把条件替换成,条件语句里的是找不到目标时的操作,重复项中目标为重复项,if不重复就可以替换了

if(nums[fast]!=nums[slow])

提问:如果非有序数组怎么处理

997.有序数组平方

997
初步想法:平方结合排序/判断是否是负数,如果负数就排序不是负数不管
存档: 快排

解决办法: 依旧是快慢双指针

数组问题中只要涉及到排序换位置全部可以用快慢指针解决;
这里引入一个int[]result 用来存放改位置后的内容
需要注意while中的条件,要保证每一个位置都比较到;明确一个条件:当left=right时也需要把平方后的内容存入新数组,所以必须是<=。

class Solution {
    public int[] sortedSquares(int[] nums) {
        int left=0;
        int right=nums.length-1;
        int[] result=new int[nums.length];
        int index=nums.length-1;
        while(left<=right)
        {
            if(nums[left]*nums[left]>nums[right]*nums[right])
            {
                result[index--]=nums[left]*nums[left++];
            }
            else
            {
                result[index--]=nums[right]*nums[right--];
            }
        }
        return result;
    }
}

类似的:合并有序数组

需注意结束条件:第二个数组全部插入就结束
思考:以上碰到的问题都是有序数组如果无序该用什么套路?

209长度最小的子数组

目的时找到子序列的长度,需要flag,不断调整。
重要概念:滑动窗口。暴力解遍历所有序列。
重要第一步:什么时候退出循环?
for(int right=0; right<nums.length; right++)
{
sum=sum+nums[right];//累加后调节窗口
//1.sum值>target;2,调节窗口到不大于target为止
while(sum>=target)
{//调节窗口的操作:1result值更新;2窗口左区间往右移一格之后的sum值}
}

59螺旋矩阵

矩阵:数组进入二维模式
思路:范围定为n平方。螺旋但是第一层确定,第二层左n-1个顺序,最右是第一层右+1;上半层从左往右顺序,下班层从右往左。
此思路大错特错。一道控制非常多条件的题。
确实要分层,也叫循环,n、2。
控制原则:左开右闭,要保持一致。

class Solution {
    public int[][] generateMatrix(int n) {
        int[][]res=new int[n][n];
        int loop=0;
        int start=0;
        int count=1;//不知道是干什么的
        int i,j;
        while(loop<n/2)
        {
            for(j=start;j<n-loop-1;j++)
            {
                res[start][j]=count++;
            }
            for(i=start;i<n-loop-1;i++)
            {
                res[i][j]=count++;
            }
            for(;j>loop;j--)
            {
                res[i][j]=count++;
            }
            for(;i>loop;i--)
            {
                res[i][j]=count++;
            }
            start=start+1;
            loop=loop+1;
        }
        if(n%2==1)
        {
            res[start][start]=count;
        }
        return res;
    }
}

Day2链表内容

链表定义

public class ListNode{
int val;
ListNode next;
public ListNode(){}
public ListNode(int val){this.val=val;}
public ListNode(int val,ListNode next){
this.val=val;
this.next=next;}
}

移除链表


class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if(head==null)
        return head;
        ListNode dummyHead=new ListNode(-1,head);//虚拟头节点
        ListNode pre=dummyHead;
        ListNode cur=head;
        while(cur!=null)
        {
            if(cur.val==val){ pre.next=cur.next;}
            else { pre=cur;}
            cur=cur.next;
        }
        return dummyHead.next;
    }
}

类似的: 237这道题在不知道pre节点的时候应该怎么操作

707设计链表

class ListNode{
    int val;
    ListNode next;
    ListNode(){}
    ListNode(int val){this.val=val;next=null;}
}
class MyLinkedList {

    ListNode head;
    int size;
    public MyLinkedList() {
        size=0;
        head=new ListNode(0);
    }
    
    public int get(int index) {
        if(index<0||index>=size)
        {
            return -1;
        }
        ListNode cur=head;
        for(int i=0;i<=index;i++)
        {
            cur=cur.next;
           // System.out.print(cur.val);
        }
        return cur.val;
    }
    
    public void addAtHead(int val) {
        addAtIndex(0,val);
       
    }
    
    public void addAtTail(int val) {
        addAtIndex(size,val);
        
    }
    
    public void addAtIndex(int index, int val) {
        if(index>size)
        {
            return;
        }
        ListNode cur=new ListNode(val);
        ListNode pred=head;
        
        if(index<0)
        {
            //cur.next=head;
            //head=cur;
            index=0;
        }
        for(int i=0;i<index;i++)
        {
            pred=pred.next;
        }
        cur.next=pred.next;
        pred.next=cur;
        size++;
    }
    
    public void deleteAtIndex(int index) {
        ListNode pred=head;
        
        if(index<0||index>=size)
        {
            return ;
        }
        size--;
        if(index==0)
        {
            head=head.next;
            return ;
        }
        for(int i=0;i<index;i++)
        {
            pred=pred.next;
        }
            pred.next=pred.next.next;
        
       
    }
}

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList obj = new MyLinkedList();
 * int param_1 = obj.get(index);
 * obj.addAtHead(val);
 * obj.addAtTail(val);
 * obj.addAtIndex(index,val);
 * obj.deleteAtIndex(index);
 */

206翻转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre=null;
        ListNode cur=head;
        while(cur!=null)
        {
            ListNode temp=cur.next;
            cur.next=pre;
            pre=cur;
            cur=temp;
        }
        return pre;
    }
}

二刷写出非常搞笑的错误:注意
class Solution {
public ListNode reverseList(ListNode head) {
ListNode dummynode=new ListNode();
ListNode cur=head;
ListNode pre=dummynode;
ListNode temp;
while(cur!=null)
{
temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
return pre;
}
}
返回的链表带了【0】尾巴。首先不需要有一个虚拟头节点,pre就够了

24两两交换链表节点

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummyhead=new ListNode();
        dummyhead.next=head;
        ListNode cur=dummyhead;
        ListNode temp1;
        ListNode temp2;
        while((cur.next!=null)&&(cur.next.next!=null))
        {
           temp1=cur.next;
           temp2=cur.next.next.next;
           cur.next=temp1.next;
           cur.next.next=temp1;
           temp1.next=temp2;
           cur=temp1;           
        }
        return dummyhead.next;
    }
}

19删除链表的倒数第n个结点

是不是也可以用前后指针,倒数第n个节点,然后让前指针在前面趟路,前指针走了n步之后后指针走路.一遍过。
注意:last指针要指向即将删除的节点的前一项。以便删除。

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyhead=new ListNode();
        dummyhead.next=head;
        ListNode cur;
        ListNode last;
        cur=dummyhead;
        last=dummyhead;
        while(cur.next!=null)
        {
            if(n<1)
            {
                last=last.next;
            }
            cur=cur.next;
            n=n-1;
        }
        last.next=last.next.next;
        return dummyhead.next;
    }
}

0207链表相交

长的链表先移到跟短链表齐平时的节点:
之后比较指针。比较墨迹。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //求长度
        ListNode cur=headA;
        int lista=0;
        while(cur!=null)
        {
            lista++;
            cur=cur.next;
        }
        cur=headB;
        int listb=0;
        while(cur!=null)
        {
            listb++;
            cur=cur.next;
        }
        int compare=listb-lista;
        ListNode temp;
        ListNode cura=headA;
        ListNode curb=headB;
        if(compare<0)
        {
            while(compare<0)
            {
                cura=cura.next;
                compare++;
            }
        }
        else
        {
            while(compare>0)
            {
                curb=curb.next;
                compare--;
            }
        }
        int count=0;
        while(cura!=null)
        {
            if(cura==curb)
            {
                count++;
            }
            cura=cura.next;
            curb=curb.next;
        }
        if(count==0)return null;
        else
        {
            while(lista-count>0)
            {
                headA=headA.next;
                lista--;
            }
            return headA;
        }
    }
}

142环形链表

需要解决:1.怎么判断有环 2.怎么确定环起始位置
1.使用快慢指针,两指针会相遇即有环。
2. 两指针相遇时地点index1,设head到入环点为x,入环点到index1为y,index1再绕回入环点距离为z:2(x+y)=x+y+(n)(y+z)
3. x=(n-1)(y+z)+z意味着当找到相遇点index1,只需要让慢指针重新从head遍历,快指针不变,再次相遇时位置必然是入环点。

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast=head;
        ListNode slow=head;
        int flag=0;
        ListNode index1;
        ListNode index2=head;
        while((fast!=null)&&(slow!=null)&&(flag!=1))
        {
            if(fast.next==null)
            {
               return null;
            }
            fast=fast.next.next; 
            slow=slow.next;
            if(fast==slow)//这部分必须放在fastslow往后走之后否则flag永远是1
            {
                flag=1;
                index1=fast;
            }
        }
        if(flag==0)
        {
            return null;
        }
        else
        {
            while(index2!=fast)
            {
                index2=index2.next;
                //我觉得都已经进行到这一步了肯定是有环的啊。无环已经返回了
                fast=fast.next;
                //之前的问题在于找到入口点时fast指针只向后走一个节点
            }
            return index2;
        }
    }
}//我的index1好像没有意义

链表部分结束

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值