LeetCode 題集感想
Q1.Two Sum
題目:給定一個數組{2,3,5,7},以及一個目標值target,要求找出兩個能使為target的集合元素的下標,并按下標小的在前排序出來。
思路:
方法1. 使用二重循環掃描數組,找到i 和 j的和為target,再找出輸出下標
超時
方法2. 使用一個map(用Java的HashMap),按<數組元素,下標>存入map,然后對每個數組元素遍歷,紀錄下target減去數組元素的值leftNum,直接在這個map里面找到key為leftNum的,取出value,就是它的序號。這樣數組的index和這個value就是兩個下標值,比較大小,輸出
通過
官方方法:
O(n2) runtime, O(1) space – Brute force:
The brute force approach is simple. Loop through each element x and find if there is another value that equals to target – x. As finding another value requires looping through the rest of array, its runtime complexity is O(n2).
O(n) runtime, O(n) space – Hash table:
We could reduce the runtime complexity of looking up a value to O(1) using a hash map that maps a value to its index.
Q56.Merge Intervals
題目:給定一系列區間,如[1,3],[2,4],[5,6],讓你講所有區間的重疊區間合并并輸出,如前者輸出[1,4],[5,6]
思路:
方法1. 先對這個區間的左值進行排序,由小到大,形成新的區間集合,然后分情況討論(三種):1.如果前一個區間右值比后一個區間左值小,則直接存入結果數組。2.else1的情況下,而且前一個區間的右值比后一個區間的右值小,合并,只保留前一個區間的左值和后一個區間的右值。3.else2的情況下,前一個區間的右值比后一個區間的右值大,保留大的。最后別忘了把最后一組區間也加入到結果數組(沒有向后比較了)
通過
Q2.Add Two Numbers
方法1.
Q3.
Q4.
Q62.Unique Paths
給定一個m*n的方塊路徑,從左上角起點起,到右下角終點,只允許向右或者向下移動,問有多少種走法。
方法1. 看清本質,這個題實際上可以看作一個組合數求值。總共可以向右移動m-1種方法,向下移動n-1種方法。由于只允許向右向下一種,而且一定最后和起來是要走完最長的那一條(舉個例子,m>n,則最后一定把所有m-1個向右走的方法都會用一遍),所以,當m>n,就是求C(m-1+n-1)(m-1);n>=m就是球C(m-1+n-1)(n-1)
通過
136.Single Numble
一個數組,除了一個元素外,其它元素都重復2遍,找出那個元素
方法1. 利用異或的性質 ab;ab 異或運算表00=0;01=1;所以直接可以用0來異或一次得到真實值,異或兩次結果不變,所以直接對數組每個元素和初始為0的result異或即可。
141.Linked List Cycle
判斷一個鏈表是否存在環
方法1. 利用一個"快慢指針",即有兩個指針指向頭節點,一個快指針每次next兩次,一個每次next一次,使用while循環,只要存在一個環,必然經過一輪的循環下,一定會相遇。反之,不存在環,一定不會相遇。時間復雜度為O(n)
通過
208.Implement Trie (Prefix Tree)
實現一個字典樹
字典樹:一個26叉樹,每個結點代表一個字母,value存一個bool值,代表是否存在這個字母。如果對一個單詞進行查找,那么它只需要O(n)的時間,插入的時候也是O(n)。
方法1. 直接貼代碼吧:
class TrieNode {
public:
// Initialize your data structure here.
TrieNode() {
for (int i = 0;i < MAX_NODE;i++) {
next[i] = 0;
}
haveValue = false;
}
static const int MAX_NODE = 26;
TrieNode* next[MAX_NODE];
bool haveValue;//true repreasent have this character
};
class Trie {
public:
Trie() {
root = new TrieNode();
}
// Inserts a word into the trie.
void insert(string s) {
TrieNode* start = root;
for (int i = 0;i < s.length();i++) {
int index = s[i] - 'a';
if (start->next[index] == 0){
start->next[index] = new TrieNode();//new character at this node.and go on for next character
}
start = start->next[index];
}
start->haveValue = true;
}
// Returns if the word is in the trie.
bool search(string key) {
TrieNode* start = root;
for (int i = 0;i < key.length();i++) {
int index = key[i] - 'a';//start with character
if (start->next[index] == 0){
return false;
}
start = start->next[index];
}
return start && start->haveValue;//entire word
}
// Returns if there is any word in the trie
// that starts with the given prefix.
bool startsWith(string prefix) {
TrieNode* start = root;
for (int i = 0;i < prefix.length();i++) {
int index = prefix[i] - 'a';
if (start->next[index] == 0){
return false;
}
start = start->next[index];
}
return start;//don't need complete all the character
}
private:
TrieNode* root;
};
// Your Trie object will be instantiated and called as such:
// Trie trie;
// trie.insert("somestring");
// trie.search("key");
通過
206. Reverse Linked List
就是簡單的反轉鏈表,要求有迭代和遞歸兩種解法
1.迭代法
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == NULL){return NULL;}
ListNode* prev = head;
ListNode* current = head->next;
ListNode* next;
while (current) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
head->next = NULL;
head = prev;
return head;
}
};
2.遞歸法
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == NULL){
return NULL;//fuck
}
if(head->next == NULL){
return head;//stop
}
ListNode* next = head->next;//head will stay here
ListNode* start = reverseList(next);
head->next = NULL;
next->next = head;
return start;
}
};