LeetCode(Medium)

目录:

  1. Linked List Cycle

  2. Binary Tree Right Side View

  3. Add Two Numbers

  4. Word Break

  5. Two Sum

  6. 3Sum

  7. Gas Station

  8. Linked List Cycle II


 

Linked List Cycle 返回目录

Given a linked list, determine if it has a cycle in it.

Follow up:
Can you solve it without using extra space?

思路:两个指针,一个指向头结点,另一个指向头结点的下一个结点,然后第一个指针每次前进一步,第二个指针每次前进两步,如果两个指针能够相遇,则存在环。

 

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     bool hasCycle(ListNode *head) 
12     {
13         if(head == NULL || head->next == NULL) 
14             return false;
15         ListNode *p = head->next;
16         while(p != NULL && p->next != NULL && p != head)
17         {
18             head = head->next;
19             p = p->next->next;
20         }
21         if(p == head)
22             return true;
23         else
24             return false;
25     }
26 };

Binary Tree Right Side View  返回目录

Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.

For example:
Given the following binary tree,

   1            <---
 /   \
2     3         <---
 \     \
  5     4       <---

 

You should return [1, 3, 4].

 思路:分别遍历根结点的左子树和右子树的右边,然后将右子树的右孩子,以及左子树的孩子中所在层数大于右子最后一个孩子所在层数的孩子保存起来即可!

 1 /**
 2  * Definition for binary tree
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 class Solution {
11 public:
12     vector<int> rightSideView(TreeNode *root) 
13     {
14         vector<int> ret;
15         if(root == NULL) 
16             return ret;
17         ret.push_back(root->val);
18         vector<int> retl;
19         vector<int> retr;
20         retl = rightSideView(root->left);
21         retr = rightSideView(root->right);
22         for(int i = 0; i < retr.size(); ++i)
23                 ret.push_back(retr[i]);
24         if(retr.size() < retl.size())
25         {
26             for(int i = retr.size(); i < retl.size(); ++i)
27                 ret.push_back(retl[i]);
28         }
29         return ret;
30     }
31 };

 


Add Two Numbers  返回目录

You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8

思路:和经典的大数乘法思路一样!

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) 
12     {
13         if(l1 == NULL && l2 == NULL) return NULL;
14         if(l1 == NULL) return l2;
15         if(l2 == NULL) return l1;
16         ListNode* result = new ListNode(0);
17         ListNode* head = result;
18         int carry = 0;
19         while(l1 != NULL || l2 != NULL)
20         {
21             int tmp;
22             if(l1 != NULL && l2 != NULL)
23             {
24                 tmp = l1->val + l2->val;
25                 l1 = l1->next;
26                 l2 = l2->next;
27             }
28             else if(l1 != NULL && l2 == NULL)
29             {
30                 tmp = l1->val;
31                 l1 = l1->next;
32             }
33             else
34             {
35                 tmp = l2->val;
36                 l2 = l2->next;
37             }
38             head->next = new ListNode((carry + tmp) % 10);
39             head = head->next;
40             carry = (carry + tmp) / 10;
41         }
42         if(carry > 0)
43         {
44             head->next = new ListNode(carry);
45         }
46         return result->next;
47     }
48 };

 


 

Word Break 返回目录

Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

For example, given
s = "leetcode",
dict = ["leet", "code"].

Return true because "leetcode" can be segmented as "leet code".

思路:对于s,分解成从第0个元素到第1,2, 3, ..., index,...的子串,用 bool f[s.size()] 数组作为标志数组,如果 0 到 index 所对应的子串在 dict 中,则f[index] = true,否则为 false.

 1 class Solution {
 2 public:
 3     bool wordBreak(string s, unordered_set<string>& wordDict) 
 4     {
 5         int size = s.size();
 6         if (0 == size)  return true;
 7         if (0 == wordDict.size())   return false;
 8 
 9         //f[i]表示前[0, i]字符是否匹配
10         bool* f = new bool[size];
11         for (int i = 0; i < size; ++i)
12             f[i] = false;
13     
14         for (int i = 0; i < size; ++i)
15         {
16             for (int j = i; j >= 0; --j)
17             {
18                 if (0 == j || f[j - 1])
19                 {
20                     if (wordDict.find(s.substr(j, i - j + 1)) != wordDict.end())
21                     {
22                         f[i] = true;
23                         break;
24                     }
25                 }
26             }
27         }
28     
29         bool re = f[size - 1];
30     
31         delete[] f;
32     
33         return re;            
34     }
35 };

 

程序是从一位网友那里复制过来的,有一点难懂,下面结合题中所述,走一遍程序:

  • i == 0, j == 0;  满足条件 j == 0调用find(),s.substr(j, i - j + 1) == "l",找不到,f[0]依旧为 false, --j, j < 0内层for终止  
  • i == 1, j == 1,if语句的条件不满足,j--, j == 0, 满足if 的 j == 0,调用find(), s.substr(j, i - j + 1) == "le",找不到,f[1]依旧为 false, --j, j < 0内层for终止,同理f[2]也依旧是false
  • i == 3, j == 3, 因为 j != 0,且f[j - 1] == false, if 语句的条件不满足, 于是  j 递减,知道 j == 0 时,if 判读为真,执行 find(),  s.substr(j, i - j + 1) == "leet",在 dict 中找到,f[3] = true
  • i == 4, j == 4, 因为 f[3] == true, if 语句满足 --> find(), s.substr(j, i - j + 1) == s.substr(4, 1) == "", 找不到,f[4] = false, j递减,知道 j == 0时再次满足 if 条件,find(), s.substr(j, i - j + 1) == ‘leetc’,找不到,如此继续
  • 可以看出,要是满足题目要求,f[s.size() - 1]必然为true

 


 

Two Sum  返回目录

Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

 1 class Solution {
 2 public:
 3     vector<int> twoSum(vector<int>& nums, int target) 
 4     {
 5         int i, sum;
 6         vector<int> results;
 7         map<int, int> hmap;
 8         for(i=0; i<nums.size(); i++)
 9         {
10             // 元素值作为key,元素位置作为value
11             if(!hmap.count(nums[i]))
12             {
13                 hmap.insert(pair<int, int>(nums[i], i));
14             }
15             if(hmap.count(target-nums[i]))
16             {
17                 int n=hmap[target-nums[i]];
18                 // 这里需要判断一下,否则对于
19                 // 输入:[1,2,3], 2
20                 // 会出现输出:[1, 1]
21                 if(n != i)
22                 {
23                     results.push_back(n+1);
24                     results.push_back(i+1);
25                     return results;
26                 }
27 
28             }
29         }
30         return results;
31     }
32 };

3Sum  返回目录

Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
  • The solution set must not contain duplicate triplets.

 

    For example, given array S = {-1 0 1 2 -1 -4},

    A solution set is:
    (-1, 0, 1)
    (-1, -1, 2)
 1 class Solution {
 2 public:
 3     vector<vector<int> > threeSum(vector<int> &num) 
 4     {   
 5         int n = num.size();
 6         sort(num.begin(), num.end());
 7         vector<vector<int> > res;
 8         for(int i = 0; i < n-2; i++) // 注意这里是n-2
 9         {
10             if(i > 0 && num[i] == num[i-1])continue;//重复的元素不用计算
11             int target2 = 0 - num[i];
12             twoSum(num, i+1, target2, res);
13         }
14         return res;
15     }
16 
17     void twoSum(vector<int> &sortedNum, int start, int target, vector<vector<int> >&res)
18     {
19         int head = start, tail = sortedNum.size() - 1;
20         while(head < tail)
21         {
22             int tmp = sortedNum[head] + sortedNum[tail];
23             if(tmp < target)
24                 head++;
25             else if(tmp > target)
26                 tail--;
27             else
28             { 
29                 res.push_back(vector<int>{sortedNum[start-1], sortedNum[head], sortedNum[tail]});
30                 
31                 //为了防止出现重复的二元组,跳过重复元素
32                 int k = head+1;
33                 while(k < tail && sortedNum[k] == sortedNum[head])k++;
34                 head = k;
35                 
36                 k = tail-1;
37                 while(k > head && sortedNum[k] == sortedNum[tail])k--;
38                 tail = k;
39             }
40         }
41     }
42 };

Gas Station  返回目录

There are N gas stations along a circular route, where the amount of gas at station i is gas[i].

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.

Return the starting gas station's index if you can travel around the circuit once, otherwise return -1.

Note:
The solution is guaranteed to be unique.

 1 class Solution {
 2 public:
 3     int canCompleteCircuit(vector<int> &gas, vector<int> &cost) {
 4         int n = gas.size();
 5         vector<int> v(n);
 6         for (int i = 0; i < n; i++) v[i] = gas[i] - cost[i];
 7         int start = 0, end = 0, gasInTank = 0;
 8         while (start < n) 
 9         {
10             while (gasInTank >= 0 && end < start + n) gasInTank += v[(end++) % n];
11             //如果剩余汽大于于0,并且遍历了n个加油站
12             if (gasInTank >= 0 && end == start + n) return start;
13             
14             gasInTank -= v[start++];
15         }
16         return -1;
17     }
18 };

 Linked List Cycle II 返回目录

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Follow up:
Can you solve it without using extra space?

 解析:http://blog.csdn.net/sysucph/article/details/15378043

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode *detectCycle(ListNode *head) 
12     {
13         if(head == NULL)
14             return NULL;
15         ListNode *ptr1 = head;
16         ListNode *ptr2 = head;
17         
18         while(ptr2->next != NULL && ptr2->next->next != NULL)
19         {
20             ptr1 = ptr1->next;
21             ptr2 = ptr2->next->next;
22             if(ptr1 == ptr2)
23             {
24                 ptr1 = head;
25                 while(ptr1 != ptr2)
26                 {
27                     ptr1 = ptr1->next;
28                     ptr2 = ptr2->next;
29                 }
30                 return ptr1;
31             }
32             
33         }
34         return NULL;
35     }
36 };

 

 

  

posted @ 2015-04-26 16:18  90Zeng  阅读(503)  评论(0编辑  收藏  举报