LeetCode算法題

第1題https://leetcode-cn.com/problems/two-sum/node

兩數之和算法

給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。數組

你能夠假設每種輸入只會對應一個答案。可是,你不能重複利用這個數組中一樣的元素。優化

示例:spa

給定 nums = [2, 7, 11, 15], target = 9code

由於 nums[0] + nums[1] = 2 + 7 = 9
因此返回 [0, 1]blog

常規算法排序

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        res:
        for (int i = 0;i < nums.length;i++) {
            for (int j = i + 1;j < nums.length;j++) {
                if (nums[i] + nums[j] == target) {
                    result[0] = i;
                    result[1] = j;
                    break res;
                }
            }
        }
        return result;
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] a = {2,7,11,15};
        int[] result = solution.twoSum(a,9);
        for (int i = 0;i < result.length;i++) {
            System.out.println(result[i]);
        }
    }
}

運行結果leetcode

0
1rem

但該算法的時間複雜度爲O(n^2)的,因此咱們考慮將該算法下降到O(n)級別

public class Solution1 {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> map = new HashMap<>(nums.length);
        for (int i = 0;i < nums.length;i++) {
            int pre = target - nums[i];
            Integer preIndex = map.get(pre);
            if (preIndex != null) {
                return new int[] {preIndex,i};
            }
            map.put(nums[i],i);
        }
        return null;
    }

    public static void main(String[] args) {
        Solution1 solution = new Solution1();
        int[] a = {2,7,11,15};
        int[] result = solution.twoSum(a,9);
        for (int i = 0;i < result.length;i++) {
            System.out.println(result[i]);
        }
    }
}

運行結果

0
1

第2題https://leetcode-cn.com/problems/add-two-numbers/

兩數相加

給出兩個 非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式存儲的,而且它們的每一個節點只能存儲 一位 數字。

若是,咱們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。

您能夠假設除了數字 0 以外,這兩個數都不會以 0 開頭。

示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
緣由:342 + 465 = 807

正面剛

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        String a = "";
        while (l1 != null) {
            a += l1.val;
            l1 = l1.next;
        }
        a = new StringBuffer(a).reverse().toString();
        String b = "";
        while (l2 != null) {
            b += l2.val;
            l2 = l2.next;
        }
        b = new StringBuffer(b).reverse().toString();
        String result = "";
        boolean add = false;
        int d = 0;
        int len;
        if (a.length() < b.length()) {
            len = b.length();
        }else {
            len = a.length();
        }
        for (int i = 0;i < len;i++) {
            if (add) {
                if (i < a.length() && i < b.length()) {
                    d = Integer.parseInt(a.substring(a.length() - 1 - i, a.length() - i))
                            + Integer.parseInt(b.substring(b.length() - 1 - i, b.length() - i)) + 1;
                }else if (i >= a.length()) {
                    d = Integer.parseInt(b.substring(b.length() - 1 - i, b.length() - i)) + 1;
                }else if (i >= b.length()) {
                    d = Integer.parseInt(a.substring(a.length() - 1 - i, a.length() - i)) + 1;
                }
            }else {
                if (i < a.length() && i < b.length()) {
                    d = Integer.parseInt(a.substring(a.length() - 1 - i, a.length() - i))
                            + Integer.parseInt(b.substring(b.length() - 1 - i, b.length() - i));
                }else if (i >= a.length()) {
                    d = Integer.parseInt(b.substring(b.length() - 1 - i, b.length() - i));
                }else if (i >= b.length()) {
                    d = Integer.parseInt(a.substring(a.length() - 1 - i, a.length() - i));
                }
            }
            if (d >= 10) {
                result += String.valueOf(d).substring(1,2);
                add = true;
            }else {
                result += String.valueOf(d);
                add = false;
            }
        }
        if (add) {
            result += 1;
        }
        ListNode node = new ListNode(Integer.parseInt(result.substring(0,1)));
        ListNode ret = node;
        for (int i = 1;i < result.length();i++) {
            node.next = new ListNode(Integer.parseInt(result.substring(i,i + 1)));
            node = node.next;
        }
        return ret;
    }
}

第2題的優化

根據上面比較複雜的寫法,根據其原理作了極簡優化

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

曬一下成績

第3題https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

無重複字符的最長子串

給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。

示例 1:

輸入: "abcabcbb"
輸出: 3 
解釋: 由於無重複字符的最長子串是 長度爲 3。"abc",因此其

示例 2:

輸入: "bbbbb"
輸出: 1
解釋: 由於無重複字符的最長子串是 ,因此其長度爲 1。"b"

示例 3:

輸入: "pwwkew"
輸出: 3
解釋: 由於無重複字符的最長子串是 ,因此其長度爲 3。
     請注意,你的答案必須是 子串 的長度, 是一個子序列,不是子串。"wke""pwke"

這道題使用暴力解題是會超時的。比方說這樣

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Set<Character>,Integer> map = new HashMap<>();
        Set<Character> key = new HashSet<>();
        int from = 0;
        String s1 = s;
        while (!s.equals("")) {
            for (int i = 0; i < s.length(); i++) {
                if (!key.contains(s.charAt(i))) {
                    key.add(s.charAt(i));
                    map.put(key, key.size());
                } else {
                    map.put(key, key.size());
                    key.clear();
                    key.add(s.charAt(i));
                }
            }
            from++;
            s = s1.substring(from);
            key.clear();
        }
        return map.values().stream().max(Comparator.comparing(x -> x)).orElse(0);
    }
}

滑動窗口法:使用一個帶邊界的集合來不斷調整邊界範圍來獲取咱們須要的結果

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        Set<Character> set = new HashSet<>();
        int n = s.length();
        int maxlen = 0;
        int i = 0;
        int j = 0;
        while (i < n && j < n) {
            if (!set.contains(s.charAt(j))) {
                set.add(s.charAt(j));
                j++;
                maxlen = Math.max(maxlen,j - i);
            }else {
                set.remove(s.charAt(i));
                i++;
            }
        }
        return maxlen;
    }
}

第4題https://leetcode-cn.com/problems/median-of-two-sorted-arrays/

4. 尋找兩個有序數組的中位數

給定兩個大小爲 m 和 n 的有序數組 nums1 和 nums2

請你找出這兩個有序數組的中位數,而且要求算法的時間複雜度爲 O(log(m + n))。

你能夠假設 nums1 和 nums2 不會同時爲空。

示例 1:

nums1 = [1, 3]
nums2 = [2]

則中位數是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

則中位數是 (2 + 3)/2 = 2.5

以前我覺得這道題是不容許重複值的

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        SortedSet<Integer> set = new TreeSet<>();
        SortedMap<Integer,Integer> map = new TreeMap<>();
        double ret;
        for (int i = 0;i < nums1.length;i++) {
            set.add(nums1[i]);
        }
        for (int i = 0;i < nums2.length;i++) {
            set.add(nums2[i]);
        }
        int len = set.size();
        for (int i = 1;i <= len;i++) {
            map.put(i,set.first());
            set.remove(set.first());
        }
        if ((map.size() & 1) == 0) {
            if (map.size() > 2) {
                SortedMap<Integer, Integer> subMap = map.subMap(map.size() / 2, map.size() / 2 + 2);
                ret = (subMap.get(subMap.firstKey()) + subMap.get(subMap.lastKey())) / 2.0;
            }else {
                ret = (map.get(map.firstKey()) + map.get(map.lastKey())) / 2.0;
            }
        }else {
            if (map.size() > 1) {
                SortedMap<Integer, Integer> subMap = map.subMap(map.size() / 2 + 1, map.size() / 2 + 2);
                ret = subMap.get(subMap.firstKey());
            }else {
                ret = map.get(map.firstKey());
            }
        }
        return ret;
    }
}

可是提交給leetCode是不能經過的,實際上它容許重複值。

如今改用歸併排序,結果能夠經過了,但實際上在歸併排序中的時間複雜度爲O(m+n),並不能知足時間複雜度的要求

class Solution1 {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int i = 0;
        int j = 0;
        int[] data = new int[nums1.length + nums2.length];
        for (int k = 0;k < data.length;k++) {
            if (i >= nums1.length) {
                data[k] = nums2[j];
                j++;
            }else if (j >= nums2.length) {
                data[k] = nums1[i];
                i++;
            }else if (nums1[i] < nums2[j]) {
                data[k] = nums1[i];
                i++;
            }else {
                data[k] = nums2[j];
                j++;
            }
        }
        if ((data.length & 1) == 1) {
            return data[data.length / 2];
        }else {
            return (data[data.length / 2 - 1] + data[data.length / 2]) / 2.0;
        }
    }
}

以後咱們會改用二分查找法才能真正知足算法複雜度的要求。

相關文章
相關標籤/搜索