O(n)
,空間複雜度爲 O(n)
。Null
,則 代表鏈表無環。若遍歷的節點在哈希表中已存在,則代表鏈表有環。/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {boolean} */ var hasCycle = function(head) { let nodesSeen = new Set(); if(head === null || head.next === null){ return false; } while(head !== null){ if(nodesSeen.has(head)){ return true; } else{ nodesSeen.add(head); } head = head.next; } return false; };
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ public boolean hasCycle(ListNode head) { Set<ListNode> nodesSeen = new HashSet<>(); while (head != null) { if (nodesSeen.contains(head)) { return true; } else { nodesSeen.add(head); } head = head.next; } return false; }
O(n)
,空間複雜度爲 O(1)
。Refjavascript
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: bool hasCycle(ListNode *head) { if(head == NULL){ return false; } ListNode *walker = head; //moves one step each time ListNode *runner = head; //moves two step each time while(runner->next != NULL && runner->next->next != NULL){ walker = walker->next; runner = runner->next->next; if(walker == runner){ return true; } } return false; } };
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {boolean} */ var hasCycle = function(head) { if(head === null) { return false; } var walker = new ListNode(); var runner = new ListNode(); walker = head; runner = head; while(runner.next!==null && runner.next.next!==null) { walker = walker.next; runner = runner.next.next; if(walker === runner) return true; } return false; };
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public boolean hasCycle(ListNode head) { if (head == null || head.next == null) { return false; } ListNode slow = head; ListNode fast = head.next; while (slow != fast) { if (fast == null || fast.next == null) { return false; } slow = slow.next; fast = fast.next.next; } return true; } }
# Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = x # self.next = None class Solution(object): def hasCycle(self, head): """ :type head: ListNode :rtype: bool """ if head == None or head.next == None: return False slow = fast = head while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: return True return False
LeetCode - 141. Linked List Cycle 中,完成了鏈表是否有環的判斷。在此基礎上,本題實現對環起點的判斷和環長度的計算。html
下面結合 LeetCode 141/142 - Linked List Cycle | CNBlogs 參考連接,對環起點的判斷和環長度的計算進行分析。java
設鏈表起點距離環的起點距離爲a
,圈長爲n
,當 walker
和 runner
相遇時,相遇點距離環起點距離爲b
,此時 runner
已繞環走了k
圈,則node
walker
走的距離爲 a+b
,步數爲 a+b
runner
速度爲 walker
的兩倍,runner
走的距離爲 2*(a+b)
,步數爲 a+b
runner
走的距離爲 a+b+k*n=2*(a+b)
,從而 a+b=k*n
,a=k*n-b
walker
走 a
步,runner
走 (k*n-b)
步。當 k=1
時,則爲 (n-b)
步令 walker
返回鏈表初始頭結點,runner
仍在相遇點。此時,令 walker
和 runner
每次都走一步距離。當 walker
和 runner
相遇時,兩者所在位置即環的起點。python
證實過程以下。git
walker
走 a
步,到達環的起點;runner
初始位置爲 2(a+b)
,走了 a
步以後,即 kn-b
步以後,所在位置爲 2(a+b)+kn-b=2a+b+kn= a+(a+b)+kn=a+2kn
。所以,runner
位置是環的起點。正則表達式
// runner走的位置 2(a+b) + a = 3a + 2b //消去b b = k*n - a = 3a + 2*(k*n - a) = a + 2kn
在上述判斷環的起點的基礎上,求解環的長度。函數
walker
和 runner
相遇時,兩者所在位置即環的起點。此後,再讓 walker
每次運動一步。walker
走 n
步以後,walker
和 runner
再次相遇。walker
所走的步數便是環的長度。注意,在while()
中須要使用break
及時跳出循環,不然提交時會出現超時錯誤Time Limit Exceeded
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *detectCycle(ListNode *head) { if(head == NULL){ return NULL; } bool hasCycle = false; ListNode *walker = head; //moves one step each time ListNode *runner = head; //moves two step each time while(runner->next != NULL && runner->next->next != NULL){ walker = walker->next; runner = runner->next->next; if(walker == runner){ hasCycle = true; break; //跳出循環 } } if(hasCycle == true){ walker = head; while(walker != runner){ walker = walker->next; runner = runner->next; } return walker; } return NULL; } };
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {ListNode} */ var detectCycle = function(head) { if(head === null || head.next === null){ return null; } // Tip - new ListNode() 建立可省略,節省代碼運行時間 // let walker = new ListNode(); // one steps // let runner = new ListNode(); // two steps let walker = head; let runner = head; let hasCycle = false; while(runner.next !== null && runner.next.next !== null){ runner = runner.next.next; walker = walker.next; if(runner === walker){ hasCycle = true; break; //jump loop } } if(hasCycle){ walker = head; while(walker !== runner){ runner = runner.next; walker = walker.next; } return walker; } return null; };
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode detectCycle(ListNode head) { if(head == null || head.next == null){ return null; } ListNode walker = head; ListNode runner = head; boolean hasCycle = false; while(runner.next != null && runner.next.next != null){ walker = walker.next; runner = runner.next.next; if(walker == runner){ hasCycle = true; break; //jump loop } } if(hasCycle){ walker = head; while(walker != runner){ walker = walker.next; runner = runner.next; } return walker; } return null; } }
# Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = x # self.next = None class Solution(object): def detectCycle(self, head): """ :type head: ListNode :rtype: ListNode """ if head == None or head.next == None: return None runner = walker = head hasCycle = False while runner and runner.next: runner = runner.next.next walker = walker.next if runner == walker: hasCycle = True break if hasCycle: walker = head while walker != runner: walker = walker.next runner = runner.next return walker return None
將一正整數的各個位數相加(即橫向相加)後,若加完後的值大於等於10的話,則繼續將各位數進行橫向相加直到其值小於十爲止所獲得的數,即爲數根 (
Digit Root
)
本題目爲求解一個非負整數的數根。參考 Digit Root | Wikipedia 能夠了解數根的公式求解方法。oop
從上圖總結規律,對於一個 b
進制的數字 (此處針對十進制數,b
=10),其 數字根 (digit root
) 能夠表達爲ui
dr(n) = 0 if n == 0 dr(n) = (b-1) if n != 0 and n % (b-1) == 0 // 9的倍數且不爲零,數根爲9 dr(n) = n mod (b-1) if n % (b-1) != 0 // 不是9的倍數且不爲零,數根爲對9取模
或者
dr(n) = 1 + (n - 1) % 9
class Solution { public: int addDigits(int num) { return 1 + (num - 1) % 9; } };
/** * @param {number} num * @return {number} */ var addDigits = function(num) { return 1 + (num - 1) % 9; };
class Solution { public int addDigits(int num) { if (num == 0){ return 0; } if (num % 9 == 0){ return 9; } else { return num % 9; } } }
class Solution: def addDigits(self, num: int) -> int: """ :type num:int :rtype :int """ if num == 0: return 0 elif num%9 == 0: return 9 else: return num%9
對輸入參數進行異或位運算獲得一個二進制數值,再計算其中的數字 1
的個數便可。
在代碼實現中,能夠結合語言內置的API或方法,簡化求解過程。
/** * @param {number} x * @param {number} y * @return {number} */ var hammingDistance = function(x, y) { let xor = x^y; let total = 0; for(let i=0;i<32;i++){ // Number型 佔32位 total += (xor>>i) &1; } return total; };
因爲 Number
型佔 32 位,所以,須要異或的結果進行32次移位,循環判斷其中的數字 1
的個數。
下面考慮簡化上述求解過程。
radix
進制格式轉換爲字符串。能夠將異或結果轉換爲 2 進制字符串。1
,將 0
替換爲空。/** * @param {number} x * @param {number} y * @return {number} */ var hammingDistance = function(x, y) { return (x ^ y).toString(2).replace(/0/g, '').length; };
Java中,Integer.bitCount() 函數能夠返回輸入參數對應二進制格式數值中數字 1
的個數。
public class Solution { public int hammingDistance(int x, int y) { return Integer.bitCount(x^y); //XOR } }
C++ 中, int __builtin_popcount 函數能夠返回輸入參數對應二進制格式數值中數字 1
的個數。
class Solution { public: int hammingDistance(int x, int y) { return __builtin_popcount(x^y); } };
islands
個數。若不考慮島嶼的周圍,則對應的周長爲 4 * islands
neighbours
。爲了簡化求解,對於全部島嶼,只考慮其左側和頂部的鄰居狀況。4 * islands - 2 * neighbours
public class Solution { public int islandPerimeter(int[][] grid) { int islands = 0, neighbours = 0; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[i].length; j++) { if (grid[i][j] == 1) { islands++; // count islands if (i !=0 && grid[i - 1][j] == 1) neighbours++; // count top neighbours if (j !=0 && grid[i][j - 1] == 1) neighbours++; // count left neighbours } } } return islands * 4 - neighbours * 2; } }
class Solution { public: int islandPerimeter(vector<vector<int>>& grid) { int count = 0, repeat = 0; for (int i = 0; i<grid.size(); i++) { for (int j = 0; j<grid[i].size(); j++) { if (grid[i][j] == 1) { count++; if (i!= 0 && grid[i-1][j] == 1) repeat++; if (j!= 0 && grid[i][j - 1] == 1) repeat++; } } } return 4 * count - repeat * 2; } };
/** * @param {number[][]} grid * @return {number} */ var islandPerimeter = function(grid) { var count=0; var repeat=0; for(var i=0;i<grid.length;i++){ for(var j=0;j<grid[i].length;j++){ if(grid[i][j] === 1){ count++; if((i!==0) && (grid[i-1][j]===1)){ repeat++; } if((j!==0) && (grid[i][j-1]===1)){ repeat++; } } } } return 4*count-2*repeat; };