Leetcode 21-30 刷题笔记(非困难题目)

21.合并两个有序链表

该题目思路十分简单,就是两个指针指向两个链表即可然后进行比较结果从而指针移动,这里直接放上代码。

    //合并两个有序链表
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = new ListNode();
        ListNode temp = head;

        while(l1 != null && l2 != null) {
            if(l1.val > l2.val) {
                temp.next = new ListNode(l2.val);
                temp = temp.next;
                l2 = l2.next;
            }else {
                temp.next = new ListNode(l1.val);
                temp = temp.next;
                l1 = l1.next;
            }
        }

        while(l1 != null) {
            temp.next = new ListNode(l1.val);
            temp = temp.next;
            l1 = l1.next;
        }

        while (l2 != null) {
            temp.next = new ListNode(l2.val);
            temp = temp.next;
            l2 = l2.next;
        }

        return head.next;
    }

22.有效括号生成

这个题目主要的思想是使用回溯法,是回溯法的经典例题之一。

首先我们需要知道什么事有效括号,即在你添加下一位括号时(左括号/右括号),需要考虑此时的左括号和右括号数量。

1.((),这种情况你就可以插入左括号或者右括号(left > right)。
2.(()),这种情况你就能插入左括号(left = right)。
3.()),这种情况就是典型的违法,所以需要摒弃。

    //生成有效括号
    public List<String> generateParenthesis(int n) {
        List<String> list = new ArrayList<>();
        backTrace(list,new StringBuilder(),0,0,n);
        return list;
    }

    public void backTrace(List<String> list,StringBuilder stringBuilder, int left, int right, int n) {
        // 出口条件
        if(left == n && right == left) {
            list.add(stringBuilder.toString());
            return;
        }
        //添加左括号
        if(left + 1 <= n) {
            stringBuilder.append("(");
            backTrace(list,stringBuilder,left + 1,right,n);
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        }

        //添加右括号
        if(right + 1 <= left) {
            stringBuilder.append(")");
            backTrace(list,stringBuilder,left,right + 1,n);
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        }
    }

24.两两交换链表结点

该题目就是一个链表的结点交换,主要考察这个指针的来回变换以及空节点判断处理问题。

1.我们进行交换时肯定是以2个结点为一个单位进行处理,如果不满足则说明到头了,则直接返回即可。

2.针对于这种需要交换头结点的题目,我个人建议设置一个虚拟头结点,这样方便一些。

剩下就没有什么难度了,直接上代码

    //两两交换
    public ListNode swapPairs(ListNode head) {
    	//看他是否满足两个节点的要求
        if(head == null || head.next == null) {
            return head;
        }
        ListNode nowHead = new ListNode();
        nowHead.next = head;

        ListNode prev = nowHead;
        ListNode first = head;
		//说明第一个结点不存在,直接退出循环
        while(first != null) {
            ListNode second = first.next;
            //说明第二个结点不存在,跳出循环
            if(second == null) {
                break;
            }

            first.next = second.next;
            second.next = first;
            prev.next = second;

            prev = first;
            first = first.next;
        }

        return nowHead.next;
    }

26.删除排序树组中重复元素

题目中已经说明是排序数组,所以我们只需要记录上一次出现的元素是什么就行了,然后不重复出现时直接覆盖掉Index记录的非重复元素和非重复元素个数。

1.如果当前元素和prev重复则跳过。
2.如果不重复则将prev更改为现在的值,并且直接赋值给index。

这种方法虽然会直接覆盖掉原来数值,但是考虑到被覆盖的元素一定是被访问过的所以针对盖提问题不大。

    //删除排序数组中重复元素(这里指将不重复放到前面,返回不重复元素数目)
    public int removeDuplicates(int[] nums) {
        if(nums.length == 0) {
            return 0;
        }

        int index = 1;
        int prev = nums[0];

        for(int i=1; i<nums.length; i++) {
            //说明重复
            if(prev == nums[i]) {
                continue;
            }
            prev = nums[i];
            nums[index++] = nums[i];
        }

        return index;
    }

27.移除元素

和26题如出一辙,直接上代码就行了

    //原地移除元素
    public int removeElement(int[] nums, int val) {
        int index = 0;
        for(int i=0; i<nums.length; i++) {
            if(nums[i] == val) {
                continue;
            }
            nums[index++] = nums[i];
        }
        return index;
    }

28.实现strStr()

该题的解决办法很多,这里我是用的是滑动窗口的思想,因为我们需要找到第一次出现该字符串的下标。

直接上代码吧,就是一个单纯截取字符串比对。

    //在haystack中找到第一次出现needle位置,并返回
    public int strStr(String haystack, String needle) {
        int H_len = haystack.length();
        int N_len = needle.length();
        
        for(int start=0; start<H_len-N_len+1; start++) {
            if (haystack.substring(start,start+N_len).equals(needle)){
                return start;
            }
        }
        return -1;
    }

29.两数相除

该题目的要求是不允许使用除法进行运算,mod运算实现除法(余数扔掉)。

我们首先知道除法其实就是一系列的减法操作。

就比如13 / 2举例:
我们可以分解成13 =(2 + 2 + 2)* 2 + 1(这个1是余数可以不要)
18 / 2;
18 = (8 + 1)* 2

主要思路是我们通过每次将除数翻倍的方式最快找到他的除数,同时记录翻倍的次数(一开始次数times = 1),这里我们不采用将除数次数+1的方式是因为这样其实就是暴力求解,我们翻倍的方式时间复杂度logn搜索,效率更高

这里需要注意的一点就是越界的问题,考虑到将MIN_INT除-1成MAX_INT会出现越界问题,所以我们干脆就将全部转换为负数进行计算,最后再根据情况判断结果是整数还是负数(正负得负之类的)

在我们进行翻倍的时候需要考虑到是否会越界(MIN_INT),所以需要在这里进行一个判断

    //两数相除
    public int divide(int dividend, int divisor) {
        if(dividend == 0) {
            return 0;
        }
        if(divisor == 1) {
            return dividend;
        }
        if(divisor == -1) {
            if(dividend == Integer.MIN_VALUE) {
                //导致越界的
                return Integer.MAX_VALUE;
            }else {
                return -dividend;
            }
        }
        int result = 0;
        boolean symbol = true;
        if((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) {
            symbol = false;
        }
        //全部转化为负数,防止越界
        if(dividend > 0) {
            dividend = -dividend;
        }
        if(divisor > 0) {
            divisor = -divisor;
        }

        while (dividend <= divisor) {
            int divide = divisor;
            //将除数翻倍次数
            int times = 1;
            //越界判断
            while((long) divide + divide <= Integer.MIN_VALUE && dividend <= divide + divide) {
                times <<= 1;
                divide <<= 1;
            }
            dividend -= divide;
            result += times;
        }

        return symbol ? result:-result;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值