[LeetCode力扣][中等难度]算法思想和代码(持续更新)

2,736 阅读3分钟

1.(2019.6.3)题目:给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
  • 算法思想

这道题比较简单,由于两个数是逆序存储的,所以只要从表头开始每一位对齐相加,同时要判断是否要进位。 设置一个进位标志,在当位相加是判断是否有来自上一位的进位,然后再根据是否需要给下一位进位来更新标志。

当两个数字不对齐时,将对齐的部分加完之后,再将多余部分加在尾部,此时也要判断进位。

/**
 * Definition for singly-linked list.
 *
 * class ListNode {
 *     int val;
 *    ListNode next;
 *    ListNode(int x) { val = x; }
}*/
 
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        
        boolean c=false;
        int sum=0;
        ListNode head=new ListNode(-1);
        head.next=null;
        ListNode tail=head;
        while(l1!=null&&l2!=null){
            sum=l1.val+l2.val;
            if(c){
                sum++;
            }
            if(sum/10!=0)
                c=true;
            else
                c=false;
            sum=sum%10;
            ListNode t=new ListNode(sum);
            t.next=null;
            tail.next=t;
            tail=t;
            l1=l1.next;
            l2=l2.next;
        }
        while(l1!=null){
            sum=l1.val;
            if(c){
               sum++;
            }
            if(sum/10!=0)
                c=true;
            else
                c=false;
            sum=sum%10;
            ListNode t=new ListNode(sum);
            t.next=null;
            tail.next=t;
            tail=t;
            l1=l1.next;
        }
        while(l2!=null){
            sum=l2.val;
            if(c){
                sum++;
            }
            if(sum/10!=0)
                c=true;
            else
                c=false;
            sum=sum%10;
            ListNode t=new ListNode(sum);
            t.next=null;
            tail.next=t;
            tail=t;
            l2=l2.next;
        }
        if(c){
            ListNode t=new ListNode(1);
            t.next=null;
            tail.next=t;
            tail=t;
        }
        return head.next;
    }
}

运行结果

执行用时 : 8 ms, 在Add Two Numbers的Java提交中击败了98.80% 的用户
内存消耗 : 38.4 MB, 在Add Two Numbers的Java提交中击败了98.76% 的用户

拓展解法:栈

其实也就是将每一位加完之后判断进位,更新进位后如栈,最后边出栈边头插法建链表即可。其实差不多。

2.(2019.6.4)题目:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:
输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
  • 算法思想

(1)暴力解法:两层循环嵌套,外层循环以第i个字母开头的字串,内层循环检查该字串的前几个字母为不重复。检查重复性可以用哈希,来减少一层循环。

class Solution {
    Map<Character,Integer> h=new HashMap();
    public int lengthOfLongestSubstring(String s) {
        int max=0;
        int now=0;
        int num=s.length();
        for(int i=0;i<num;i++){
            char c=s.charAt(i);
            h.clear();
            now=count(s.substring(i));
            if(now>max)
                max=now;
            if(max>(num-i)){
                return max;
            }
        }
        return max;
    }
    public int count(String s){
        int n=s.length();
        int now=0;
        for(int i=0;i<n;i++){
            if(!h.containsKey(s.charAt(i))){
                now++;
                h.put(s.charAt(i),i);
            }
            else{
                return now;
            }
        }
        return now;
    }
}

运行结果:

执行用时 : 336 ms, 击败了6.67% 的用户
内存消耗 : 236.2 MB, 击败了5.00% 的用户

(2)优化方法:队列法。同样使用哈希来检查字符是否在队列口中。若下一个字符不在队中,则入队;若下一个字符在队列中,则先看是否需要更新最大队列长度,再出队一个字符,再重复判断。

class Solution {
 Map<Character,Integer> h=new HashMap();
    public int lengthOfLongestSubstring(String s) {
        int max=0;
        int now=0;//窗口
        int n=s.length();
        int i=0,j=0;
        while(i<n&&j<n){
            if(!h.containsKey(s.charAt(j))){//下一个字符不在窗口中
                h.put(s.charAt(j),j);
                j++;
                now++;
                if(now>max){
                    max=now;
                }
            }
            else{//下一个字符在窗口中
                h.remove(s.charAt(i),i);
                i++;
                now--;
            }
        }
        if(now>max){
            max=now;
        }
        return max;
    }
}

运行结果:

执行用时 : 45 ms, 击败了50.04% 的用户
内存消耗 : 41.4 MB, 击败了69.08% 的用户