LeetCode刷题笔记(第一周)(2)

88.合并两个有序数组

思路:(双指针)

用两个指针分别指向nums1和nums2,每次对比两个指针元素的大小,小的放到nums3(结果暂存在这个数组)中,nums3的指针和相对小的元素所在的数组的指针后移,直到某个指针到达某个数组的最后一个非0元素结束。

代码:

public void merge(int[] nums1, int m, int[] nums2, int n) {
    if(m==0){
        for(int i=0;i<n;i++){
            nums1[i]=nums2[i];
        }
    }else if(m!=0&&n!=0){
        int nums3[]=new int[m+n];
        int i1=0,i2=0,i3=0;
        while(i1<m&&i2<n){
            if(nums1[i1]<=nums2[i2]){
                nums3[i3++]=nums1[i1++];
            }else{
                nums3[i3++]=nums2[i2++];
            }
        }
        if(i1==m){
            for(int i=i2;i<n;i++)
                nums3[i3++]=nums2[i2++];
        }else if(i2==n){
            for(int i=i1;i<m;i++)
                nums3[i3++]=nums1[i1++];
        }
        for(int i=0;i<m+n;i++){
            nums1[i]=nums3[i];
        }
    }
 }

思路:(方法论)

直接调用Arrays里面的sort方法(效率低,上面那个0ms,就是空间占用大)

代码:

public void merge(int[] nums1, int m, int[] nums2, int n) {
    int nn=0;
    for(int i=m;i<m+n;i++){
        nums1[i]=nums2[nn++];
    }
    Arrays.sort(nums1);
}

思路:(逆向双指针)

和第一个方法类似,但是是从两个数组的最后一个元素进行比较,比较的结果填到nums1后面的数(nums1总长度m+n,从最后一个开始填充)。只是把那个nums3的指针放到nums1的最后一个元素。具体填充方法:两个数组最后一个非0数字对比,如果是nums1大,则把当前这个下标的元素放到最后一位非0位置,然后将原来的那个位置置为0,直到nums1后面的指针到了一个非0的位置。

代码:

public void merge(int[] nums1, int m, int[] nums2, int n) {
        if(m==0){
            int i=0;
            for(int num:nums2){
                nums1[i++]=num;
            }
        }else if(m!=0&&n!=0){
            int rear=m+n-1;//0数组尾部指针
            int rear1=m-1,rear2=n-1;//nums1和2数组尾部指针
            while(rear>=0){
                if(rear1<0){
                    nums1[rear]=nums2[rear2];
                    rear2--;
                    rear--;
                }else if(rear2<0){
                    break;
                }else{
                    if(nums1[rear1]>nums2[rear2]){
                        nums1[rear]=nums1[rear1];
                        rear--;
                        nums1[rear1]=0;
                        rear1--;
                    }else{
                        nums1[rear]=nums2[rear2];
                        rear--;
                        rear2--;
                    }
                }
                
            }
        }
 }

160.相交链表

思路:(HashSet)

利用hashset每个元素只能存一次的性质,add方法失败的话就表示有相同的两个节点,返回值就是相交节点,但是这种方法效率低

代码:

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        Set<ListNode> set=new HashSet<>();
        if(headA==null||headB==null)
            return null;
        while(headA!=null||headB!=null){
            if(headA!=null&&!set.add(headA)){
                return headA;
            }
            if(headB!=null&&!set.add(headB)){
                return headB;
            }
            if(headA!=null)headA=headA.next;
            if(headB!=null)headB=headB.next;
        }
        return null;
 }

思路:(双指针)(妙啊)

两个链表长度的和为m+n,所以设置A链表的指针为iA,B链表的指针为iB,假设两个链表相交,如果相交节点前走过的节点数相同,那肯定会在相交节点相遇;如果A的长度不等于B的长度,那么就让iA走完A链表后去走B链表,让iB走完后去走A链表的路,然后肯定会在相交节点相遇(因为相交以后所有的结点都是A和B共有的,所以数量肯定一样)如果假设两个链表不相交,就都会在遍历完两个链表后返回null,所以最坏的情况是走了m+n次,但是指针数量为常数个,所以空间复杂度O(1)

代码:

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA==null||headB==null)
            return null;
        ListNode iA=headA;
        ListNode iB=headB;
        while(iA!=iB){
            iA=iA==null?headB:iA.next;
            iB=iB==null?headA:iB.next;
        }
        return iA;
 }

415.字符串相加

思路:(双指针)

设计两个指针分别指向两个字符串的最后一个元素,new一个StringBuffer可以用append方法将每次运算得出来的结果插到尾部,最后将结果反过来就好了。主要是判断条件那里,要判断什么时候应该停掉指针,应该要运算到最长的字符串最后一位,且判断有没有进位,有进位还要继续运算。

代码:

class Solution {
    public String addStrings(String num1, String num2) {
        int i = num1.length() - 1, j = num2.length() - 1, add = 0;
        StringBuffer ans = new StringBuffer();
        while (i >= 0 || j >= 0 || add != 0) {
            int x = i >= 0 ? num1.charAt(i) - '0' : 0;
            int y = j >= 0 ? num2.charAt(j) - '0' : 0;
            int result = x + y + add;
            ans.append(result % 10);
            add = result / 10;
            i--;
            j--;
        }
        // 计算完以后的答案需要翻转过来
        ans.reverse();
        return ans.toString();
    }
}

704.二分查找

思路:(二分)

需要注意的是while循环的条件以及target小于和大于nums[mid]的时候,left和right应该怎么移动

代码:

public int search(int[] nums, int target) {
        if(target>nums[nums.length-1]||target<nums[0])
            return -1;
        else if(target==nums[0])
            return 0;
        else if(target==nums[nums.length-1])
            return nums.length-1;
        int left=0;
        int right=nums.length-1;
        while(left<=right){
            int mid=(right+left)>>1;
            if(target==nums[mid]){
                return mid;
            }else if(target<nums[mid]){
                right=mid-1;
            }else if(target>nums[mid]){
                left=mid+1;
            }
        }
        return -1;
}

83.删除排序链表中的重复项

 思路:(双指针)

就对比前后两个指针的值,如果相等,左指针的next指向右指针的next。如果不相等,将两个指针后移。结果返回head是因为头结点没有被改变。

代码:

public ListNode del(ListNode head){
        ListNode last=null;
        ListNode node=head;
        while(node!=null){
            if(last==null){
                last=node;
                node=node.next;
            }else{
                if(last.val==node.val){
                    last.next=node.next;
                }else{
                    last=last.next;
                }
                node=node.next;
            }
        }
        return head;
}

        做个第一周的小总结吧,额..确实刷的都是些简单题,而且一开始做题根本就想不太出来代码要怎么写,不会用HashMap,HashSet或者是Queue等等类型的数据结构,但是通过边刷题,边背/理解一些八股文,就很快能够掌握怎么使用这些框架集合了。

        总的来说吧,就是别懒,该刷得刷,该背得背,确实没思路的题看别人的题解,然后照着别人的思路还原出来代码,有时间多回头再刷几遍就完事了。万事开头难,加油,奥利给!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值