ARTS Week 2
Algorithm
本週的 LeetCode 題目為 1. 兩數之和
題目簡介
給定一個整數陣列 nums 和一個整數目標值 target,找出該陣列中和為目標值 target 的那兩個 整數,並返回它們的陣列下標。你可以假設每種輸入只會對應一個答案。但是,陣列中同一個元素在答案裡不能重複出現。
示例 :
輸入:nums = [2,7,11,15], target = 9
輸出:[0,1]
解釋:因為 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
題目思路
題目的思路很簡單,遍歷陣列,查詢 target - nums[0] 是否在陣列 nums 中,若在返回 0 和它的下標,若不在,查詢下一個,即 target-nums[1] 是否在陣列中,直至找到停止。為了快速查詢 target-nums[i],可以記錄下陣列中的 值——索引 的對應關係。
最終程式碼
// 自己的寫法 class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer, HashSet<Integer>> numIndexMap = new HashMap<Integer, HashSet<Integer>>(); for (int i = 0; i < nums.length; i++) { Integer num = nums[i]; if (numIndexMap.containsKey(num) == false) { numIndexMap.put(num, new HashSet<Integer>()); numIndexMap.get(num).add(i); } else { numIndexMap.get(num).add(i); } } int[] ans = new int[2]; int index = 0; for (Integer key: numIndexMap.keySet()) { Integer goalKey = target - key; if (goalKey.equals(key) == true) { if (numIndexMap.get(goalKey).size() > 1) { for (Integer temp: numIndexMap.get(goalKey)) { ans[index] = temp; index += 1; } } } else { if (numIndexMap.containsKey(goalKey) == true) { for (Integer temp: numIndexMap.get(key)) { ans[0] = temp; } for (Integer temp: numIndexMap.get(goalKey)) { ans[1] = temp; } } } } return ans; } }
但自己的寫法較為複雜,官方的寫法簡略。實際上沒有必要為每個元素都建立值—索引
的對映關係,可以等到遍歷的時候進行判斷和建立。程式碼如下:
// 官方的寫法 class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer, Integer> numIndexMap = new HashMap<Integer, Integer>(); for (int i = 0; i < nums.length; i++) { if (numIndexMap.containsKey(target - nums[i])) { return new int[]{numIndexMap.get(target - nums[i]), i}; } else { numIndexMap.put(nums[i], i); } } return new int[2]; } }
Review
本週 Review 的英文文章為:Follow boring advice。
這篇文章很短,作者分享了一些建議,這些建議在作者眼中是無聊枯燥的,我認為大部分是老調重談。雖說其中很多相信大部分人早已聽過,但做到卻並不是那麼容易,這就是知易行難。Review 這篇文章,一是希望能對大家有幫助,二是希望能提醒自己。
下面的就是作者分享的具體建議:
行動(Action)
:無論什麼事,先做起來。我們是由我們所做的事決定的,而不是所想的事定義的。任何不完美的行動都比一直思考它更好;連貫(Consistency)
:好事是建立在一個好習慣並在堅持它的過程中發生。如定期鍛鍊身體;迭代(Iteration)
:需要不時地停下來,反思,調整繼續前進。一味地做而不去反思可能會在錯誤的道路上越走越遠;複利(Compounding)
:複利不僅適用於金融領域,同樣也適用於生活中,每個細微的改變也會隨著時間推移產生巨大影響;刻意練習(Deliberate practice)
:如果想要提高某項能力,重要的是有意識的刻意訓練它;專注(Focus)
:一次只做一件事,設立明確的目標,避免分心和衝動;分治法(Divide and conquer)
:將一個大的任務分割成一個個小的任務來完成;積極樂觀和感激(Positivity and gratitude)
:對生活要保持積極樂觀,對生活中的人要懷有感激之心。
Tip
快慢指標判斷條件的細微差異。
快慢主要用在連結串列中,簡單的說快慢指標就是慢指標一次只前進一步,而快指標一次會前進兩步,這樣快指標的就會先達到 null
後,停止迴圈。示例程式碼如下:
/**
* Definition for singly-linked list.
* 單鏈表定義
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
ListNode slow = head;
ListNode fast = head;
while (判斷條件) {
slow = slow.next;
fast = fast.next.next;
}
判斷條件有兩種選擇,分別為:
(fast != null) && (fast.next != null)
(fast.next != null) && (fast.next.next != null)
當判斷條件是 (fast != null) && (fast.next != null)
,結束時慢指標所在的位置正好是後半部分的開始位置。示例如下:
1->2->3->4->5->null
s s s s
f f f f->end
1->2->3->4->null
s s s
f f f->end
而當判斷條件是 (fast.next != null) && (fast.next.next != null)
,結束時慢指標後半部分的開始位置的前一個,即正中間的位置(總個數為奇數)或者是前半部分的最後一個(總個數為偶數)。示例如下:
1->2->3->4->5->null
s s s
f f f->end
1->2->3->4->null
s s
f f->end
Share
連續四個月在朋友圈和QQ空間分享月度總結,可以基本視為養成了習慣。雖說並沒有會帶來特別大的改變,但還是收穫了不少,也感受到了一定的提升。每個評論的、點讚的人都可以視為監督者,感謝他們起到了監督自己、鞭策自己的作用,沒有他們自己很可能會在某些方面上會放縱一些。