第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; } } }
以後咱們會改用二分查找法才能真正知足算法複雜度的要求。