leetcode -- medium part

22. Generate Parentheses

 1 class Solution
 2 {
 3 private:
 4     void generateParenthesis(vector<string> &v, string s, int l, int r) // l和r记录剩余左右括号的数量
 5     {
 6         if(l == 0 && r == 0) // 当且仅当左右括号数量都为0时,正常结束
 7             v.push_back(s);
 8  
 9         if(l > 0)
10             generateParenthesis(v, s + "(", l - 1, r);
11         if(r > 0 && l < r) // 剩余的右括号数量比左括号多时才能添加右括号
12             generateParenthesis(v, s + ")", l, r - 1);
13     }
14 public:
15     vector<string> generateParenthesis(int n)
16     {
17     vector<string> v;
18     generateParenthesis(v, "", n, n);
19     return v;
20     }
21 };

括号匹配数是一个卡特兰数,f(x) = (2n)!/((n+1)! * n!) , f(3) = 5

当作dfs处理,这样得到的顺序是"("从多到少的顺序。

用python写

1 class Solution(object):
2     def generateParenthesis(self, n):
3         """
4         :type n: int
5         :rtype: List[str]
6         """
7         return ['(' + litem + ')' + ritem for i in range(n) for litem in self.generateParenthesis(i) for ritem in self.generateParenthesis(n-1-i)] or ['']

 python写法的示意图:

l、r 的值相当于left、right位置上有几个括号

按这个dfs的结果是()()(), ()(()), (())(), (()()), ((()))

 

15. 3Sum

可以用hash存一下,然后两个for循环,内部加hashSearch(-(num[i] + num[j]) ), hash部分的代码参考2sum

 1 /**
 2  * Return an array of arrays of size *returnSize.
 3  * Note: The returned array must be malloced, assume caller calls free().
 4  */
 5 
 6 typedef struct linkList{
 7     int data;
 8     int index_nums;
 9     struct linkList *ptr; 
10 }linkList;
11 _Bool hashSearch(int num1, int num2, int* index_num3, int val, int hashTSize, linkList *hashT);
12 int** threeSum(int* nums, int numsSize, int* returnSize) {
13     int hashTSize = numsSize;
14     int index_num3, target;
15     int index_set = 0;
16     int **ptr_set = calloc(1024, sizeof(int *));
17     linkList *hashT = calloc(hashTSize, sizeof(linkList));
18     
19     char mark[1024] = {0};
20     for(int i = 0; i < numsSize; i++) hashInsert(i, nums[i], hashTSize, hashT);
21     
22     for(int i = 0; i < numsSize-1; i++)
23         for(int j = i+1; j < numsSize; j++){
24             target = -(nums[i] + nums[j]);
25             if(hashSearch(i, j, &index_num3, target, hashTSize, hashT)) {
26                     // if (mark[i] && mark[j] && mark[index_num3]) continue;
27                     if (index_num3 < j) continue;
28                     ptr_set[index_set] = malloc(3 * sizeof(int));
29                     ptr_set[index_set][0] = nums[i];
30                     ptr_set[index_set][1] = nums[j];
31                     ptr_set[index_set][2] = nums[index_num3];
32                     // mark[i] = mark[j] = mark[index_num3] = 1;
33                     ++index_set;
34             }
35         }
36     *returnSize = index_set;
37     return ptr_set;
38 }
39 void hashInsert(int i, int val, int hashSize, linkList *hashT) {
40     int temp_val;
41     temp_val = (val < 0) ? -val : val;
42     linkList *temp_ptr = &hashT[temp_val % hashSize];
43     while(temp_ptr->ptr) temp_ptr = temp_ptr->ptr;
44     temp_ptr->ptr = calloc(1, sizeof(linkList));
45     temp_ptr->ptr->data = val;
46     temp_ptr->ptr->index_nums = i;
47 }
48 _Bool hashSearch(int exist_index1, int exist_index2, int* return_index, int val, int hashTSize, linkList *hashT){
49     int temp_val;
50     temp_val = (val < 0) ? -val : val;
51     linkList *temp_str = &hashT[temp_val % hashTSize];
52     for (temp_str = temp_str->ptr; temp_str; temp_str = temp_str->ptr)
53         if (temp_str->data == val && temp_str->index_nums != exist_index1 && temp_str->index_nums != exist_index2){
54             *return_index = temp_str->index_nums;
55             return true;
56         }
57     return false;
58 }
HASH

 

但是处理不了

正统方法还是用sort,排序以后两端比较。

 

2. Add Two Numbers

使用二级指针:

 1 struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2)
 2 {
 3     if (l1 == NULL)
 4         return l2;
 5     if (l2 == NULL)
 6         return l1;
 7     struct ListNode *head_l3 = NULL;
 8     struct ListNode **ppl3 = &head_l3;
 9     int v = 0;
10     while (l1 != NULL || l2 != NULL || v) {
11         if (l1 != NULL) {
12             v += l1->val;
13             l1 = l1->next;
14         }
15         if (l2 != NULL) {
16             v += l2->val;
17             l2 = l2->next;
18         }
19         struct ListNode *pl3 = (struct ListNode *) malloc(sizeof(struct ListNode));
20         pl3->next = NULL;
21         pl3->val = v % 10;
22         v /= 10;
23         
24         *ppl3 = pl3;
25         ppl3 = &pl3->next;
26         
27     }
28     return head_l3;
29 }

使用二级指针就不用使用dummy head节点,因为prePtr->next和head都是指针,用二级指针就可以不加区分地表示两者

(不加区分地表示两者的意思是:令pp = &prePtr->next 或 pp = &head, 那么*pp这个表示形式就可以表达两种语义,表达能力更强)

为了创建并链接新结点,在while循环内存在形如prePtr->next = newPtr; prePtr = newPtr;的表达,同时第一次进入while时应该实现 head = newPtr; prePtr = newPtr;

如果不使用二级指针,那么就要将第一次进入while时的行为写成 dummy->next = newPtr; prePtr = newPtr;

不使用二级指针的方式如下:

 1 struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2)
 2 {
 3     struct ListNode* res,*pt,*node;
 4     int j = 0,temp = 0;
 5     res = (struct ListNode*) malloc(sizeof(struct ListNode));
 6     res->next = NULL;
 7     pt = res;
 8     while (l1 != NULL || l2 != NULL || j!=0)
 9     {
10         node = (struct ListNode*) malloc(sizeof(struct ListNode));
11         temp = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + j;
12         node->val = temp%10;
13         j = temp/10;
14         node->next = NULL;
15         pt->next = node;
16         pt = node;
17         l1 = l1 ? l1->next : l1;
18         l2 = l2 ? l2->next : l2;
19     }
20     pt = res->next;
21     free(res);
22     return pt;
23 }

 更多二级指针用法参考:http://coolshell.cn/articles/8990.html#comment-326334 、http://coolshell.cn/articles/9859.html

 

3. Longest Substring Without Repeating Characters

因为出现的元素都是ascii字符,可以用一个128个元素的数组记录(ascii使用8位,但是头一位是0,所以范围是000 0000 ~ 0111 1111)

 1 int lengthOfLongestSubstring(char* s) {
 2   int h[128];
 3   int index1 = 0, index2 = 0;
 4   int max = 0, i = 0;
 5   for(i = 0; i < 128; i++){
 6     h[i] = -1;
 7   }
 8   
 9   while(*s != '\0'){
10     //char *s last appear at index h[*s]
11     if(h[*s] >= index1){ //repeat
12       index1 = h[*s] + 1;
13     }
14     if(index2 - index1 + 1 > max){
15         max = index2 - index1 + 1;
16     }
17     h[*s] = index2; //update char *s last position
18     index2++;
19     s++;
20   }
21   return max;
22 }

 

5. Longest Palindromic Substring

char *longestPalindrome(char *s) {
    int start = 0, end = 0;
    for (int i = 0; i < strlen(s); i++) {
        int len1 = expand(s, i, i);
        int len2 = expand(s, i, i+1);
        int len = len1 > len2? len1 : len2;
        if (len > end - start) {
            start = i - (len - 1)/2;
            end = i + len/2;
        }
    }
    int ans_len =  end - start + 2;
    char *ans = malloc(sizeof(char) * ans_len);
    strncpy(ans, s + start, end-start + 1);
    ans[end-start+1] = '\0';
    return ans;
}
int expand(char *s, int left, int right) {
    int L = left, R = right;
    while (L >= 0 && R < strlen(s) && s[L] == s[R]) {
        L--;
        R++;
    }
    return R - L - 1;
}

 

11. Container With Most Water

  

水位由两个挡板间较低的挡板决定,所以可以从两端设置index i, j,每次移动较低的挡板并计算新的面积是否是最大面积。

 1 int maxArea(int* heights, int size)
 2 {
 3     int l=0, r=size-1;
 4     int max = 0;
 5     while(l < r)
 6     {
 7         int area = (r-l)*(heights[l] < heights[r]? heights[l++] : heights[r--]);
 8         max = max > area? max : area;
 9     }
10     return max;
11 }

 

12. Integer to Roman

 1 char* intToRoman(int num) {
 2     char *M[] = {"", "M", "MM", "MMM"};
 3     char *C[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
 4     char *X[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
 5     char *I[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
 6     char *ans = malloc(sizeof(char)*20);
 7     strcat(strcat(strcat(strcat(ans,M[num/1000]),C[(num%1000)/100]), X[(num%100)/10]), I[num%10]);
 8     // snprintf(ans, 20, "%s%s%s%s", M[num/1000], C[(num%1000)/100], X[(num%100)/10], I[num%10]);
 9     return ans;
10 }

 

13. Roman to Integer

阿拉伯数字从左至右是降序的,而罗马数字除了降序也会出现升序,比如表示4的时候使用IV表示5-1.

 1 int romanToInt(char *s) {
 2 #define _M 1000
 3 #define _D 500
 4 #define _C 100
 5 #define _L 50
 6 #define _X 10
 7 #define _V 5
 8 #define _I 1
 9 
10     int result  = 0;
11     int i;
12     int last = _M;
13     for(i = 0;i < strlen(s);i++)
14     {
15         switch (s[i])
16         {
17             case 'M':
18                 result = (last >= _M ? result + _M:result + _M - (last << 1));
19                 last = _M;        
20             break;
21             case 'D':
22                 result = (last >= _D ? result + _D:result + _D - (last << 1));
23                 last = _D;
24             break;
25             case 'C':
26                 result = (last >= _C ? result + _C:result + _C - (last << 1));
27                 last = _C;
28             break;
29             case 'L':
30                 result = (last >= _L ? result + _L:result + _L - (last << 1));
31                 last = _L;
32             break;
33             case 'X':
34                 result = (last >= _X ? result + _X:result + _X - (last << 1));
35                 last = _X;
36             break;
37             case 'V':
38                 result = (last >= _V ? result + _V:result + _V - (last << 1));
39                 last = _V;
40             break;
41             case 'I':
42                 result = (last >= _I ? result + _I:result + _I - (last << 1));
43                 last = _I;
44             break;
45         }
46         
47     }
48     return result;
49 }

 

16. 3Sum Closest

这题与3sum很相似,不同之处在于不用查重,如果有等于target的就直接返回target,否则就返回最近接近的target的3sum。

 1 int cmp(int *p1, int *p2);
 2 int threeSumClosest(int* nums, int numsSize, int target) {
 3     qsort(nums, numsSize, sizeof(int), cmp);
 4     int i, l , r, sum, minoff, ans;
 5     minoff = INT32_MAX;
 6     ans = 0;
 7     for(i = 0; i < numsSize; i++){
 8         l = i + 1;
 9         r = numsSize - 1;
10         while(l < r){
11             sum = nums[i] + nums[l] + nums[r];
12             if(sum == target){
13                 return target;
14             }
15             if(abs(sum-target) < minoff){
16                 minoff = abs(sum-target);
17                 ans = sum;
18             }
19             else if(sum-target > 0){
20                 r--;
21             }
22             else {
23                 l++;
24             }
25         }
26     }
27     return ans;
28 }
29 int cmp(int *p1, int *p2)
30 {
31     return *p1-*p2;
32 }

 

17. Letter Combinations of a Phone Number

c的字符串处理很鸡肋,,,有很多手动管理内存的操作

class Solution {  
public:  
    vector<string> letterCombinations(string digits) {  
        vector<string> result;  
        DFS(digits,0,"",result);  
        return result;  
    }  
private:  
    void DFS(string digits,int cur,string path,vector<string> &result){  
        string keyboard[] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};  
        if(cur == digits.length()){  
            result.push_back(path);  
            return;  
        }//if  
        int len = keyboard[digits[cur] - '0'].length();  
        for(int i = 0;i < len;++i){  
            char c = keyboard[digits[cur] - '0'][i];  
            DFS(digits,cur + 1,path + c,result);  
        }//for  
    }  
};  

因为只能传指针(或者把字符数组包在一个结构体内传结构体),所以像DFS(digits,cur + 1,path + c,result); 这样的代码要先malloc一个指针然后用strcat把字符串连接到这个指针,还要在使用之后自己free,还是直接使用string类比较方便。

 

29. Divide Two Integers

模拟长除法

 1 int divide(int x, int y) {  
 2     // Note: The Solution object is instantiated only once.
 3 //    int x = dividend, y = divisor;
 4     if (y == 0) return INT32_MAX;
 5     if (y == -1 && x == INT32_MIN) return INT32_MAX;
 6     if (y == 1 && x == INT32_MIN) return INT32_MIN;
 7     unsigned int px = (x < 0)? -x : x;
 8     unsigned int py = (y < 0)? -y : y;
 9     int ans = 0;
10 //     printf("at first px:%u\npy:%u", px,py);
11     while(px >= py) {
12         int shift = 0;
13         while (px >= (py << shift)){
14             ++shift;
15             if(px == (py<<shift)){
16                 shift++;
17                 break;
18             }
19             // printf("py<
20         }
21         shift--;
22         
23         ans += 1 << (shift);
24         
25         px -= (py << shift);
26     }
27     return (int)((x ^ y) >> 31) ? (-ans) : (ans);  
28 }

 以上的写法相当于每次从0开始检索一个最长位,最坏的情况下每次都要检索到头,比如对于11111111..检索次数是 31 + 30 + 29 + 28 + 27 + 26 + 25 + 24...

也可以先找出一个最高位,然后从这个最高位向0检索,最坏的情况下也只用检索31次。

因为我是转成unsigned,所以要小心2147483648 << 1 得到0的情况(一开始没察觉到检查了半天,最后加了个if x == y return 1;)

 1 int divide(int x, int y) {  
 2     if (y == 0) return INT32_MAX;
 3     if (y == -1 && x == INT32_MIN) return INT32_MAX;
 4     if (y == 1 && x == INT32_MIN) return INT32_MIN;
 5     if (x == y) return 1;
 6     unsigned int px = (x < 0)? -x : x;
 7     unsigned int py = (y < 0)? -y : y;
 8     int ans = 0;
 9     int shift = 0;
10     while(px >= (py<<shift)) {
11         shift++;
12         if(px == (py<<shift)){
13             shift++;
14             break;
15         }
16     }
17     shift--;
18     while (shift >= 0) {
19         if (px >= (py << shift)) {
20             ans += (1 << shift);
21             px -= (py << shift);
22         }
23         shift--;
24     }
25     return ((x ^ y) >> 31) ? (-ans) : (ans);  
26 }

 

转载于:https://www.cnblogs.com/autoria/p/5988547.html

你可能感兴趣的:(leetcode -- medium part)