顯示具有 Recursion 標籤的文章。 顯示所有文章
顯示具有 Recursion 標籤的文章。 顯示所有文章

2026年3月8日 星期日

21. Merge Two Sorted Lists

難度: Easy

類型: Linked list,Recursion 
CPP程式下載: 21.cpp

Topic:

You are given the heads of two sorted linked lists list1 and list2.

Merge the two lists into one sorted list. The list should be made by splicing together the nodes of the first two lists.

Return the head of the merged linked list.

 

Example 1:

Input: list1 = [1,2,4], list2 = [1,3,4]
Output: [1,1,2,3,4,4]

Example 2:

Input: list1 = [], list2 = []
Output: []

Example 3:

Input: list1 = [], list2 = [0]
Output: [0]

 

Constraints:

  • The number of nodes in both lists is in the range [0, 50].
  • -100 <= Node.val <= 100
  • Both list1 and list2 are sorted in non-decreasing order.

Consideration:
Linked List combined.
1. Compare and add the smaller one. Move pointer to next. When one list is ended, add the rest of another list.
2. If both lists empty, return nullptr.

Code:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        //int iSize1=list1.size();
        //int iSize2=list2.size();
        //int i=0,j=0;
        ListNode* outlist=nullptr;
        ListNode* outlistHead=nullptr;
        ListNode* list1tmp=list1;
        ListNode* list2tmp=list2;
        if (list1==nullptr) {
            return list2;
        }
        else if (list2==nullptr) {
            return list1;
        }
        else
        {
            
            while (1) {
                if (list2->val<list1->val) {
                     if (outlistHead==nullptr) {
                         //cout << "list2->val=" << list2->val << "\n";
                         outlist=list2;
                         list2=list2->next;
                         outlistHead=outlist;
                     }
                     else {
                         //cout << "list2->val=" << list2->val << "\n";
                         
                         outlist->next=list2;
                         list2=list2->next;
                         outlist=outlist->next;
                     }
                }
                else {
                    if (outlistHead==nullptr) {
                        outlist=list1;
                         list1=list1->next;
                         outlistHead=outlist;
                    }
                    else {
                         outlist->next=list1;
                         list1=list1->next;
                         outlist=outlist->next;
                     }
                }

                if (list1==nullptr)
                {
                    outlist->next=list2;
                    //cout << "A:list2->val=" << list2->val << "\n";
                    return outlistHead;
                }
                else if (list2==nullptr)
                {
                    outlist->next=list1;
                    return outlistHead;
                }
            }
        }
    }
};

Result:
https://leetcode.com/problems/merge-two-sorted-lists/submissions/1831161763/
Accepted
208 / 208 testcases passed
tendchen
tendchen
submitted at Nov 16, 2025 16:45
Runtime
0ms
Beats100.00%
Memory
19.58MB
Beats26.66%

2025年6月1日 星期日

44. Wildcard Matching

 44. Wildcard Matching

難度: Hard
類型: String, Dynamic Programming, Greedy, Recursion
CPP程式下載: 44.cpp

前情題要:
含任意字元 '?' 與 '*' 的 pattern match。












思考方式:
1. '*' 是一個特殊的存在, 可以代表任意字串, 也可以是空字串。'?' 則是任意一個字元, 不能為空字串。
2. 首先, 先尋找 '*' 在 pattern 字串中有幾個。若是沒有, 那就是字串 s 和 p 要完全match。若是只有一個 '*', 就把 p 字串分成 '*' 前, 以及 '*' 後兩個字串, 前字串與 s 字串從前面開始比對, 後字串從 s 字串最後方開始往前比對, 若都能 match 且 s 字串中間還有其他字元, 或是剛剛好沒有其他字元, 那麼就是 pattern match。
3. 若 '*' 在 p 字串中有兩個以上, 就把 p 字串切成三份, 第一個 '*' 前, 最後一個 '*' 後, 以及中間含 n-2 個 '*' 的字串。一樣前後字串各自從前後單獨比對。然後中間的字串每兩個 '*' 夾在中間的的字元順序與個數, s 的中間字串要和 p 的中間字串彼此字元順序要相同, 長度相同, 但可以在 s 字串中間隔幾個任意字元組合後再相同。

複雜度思考:

Time Complexity: O( (n-2)*strlen(s) ) 

Space Complexity: O( x )

結果:

Runtime: 3 ms, Beats: 96.32%

Memory: 12.97 MB, Beats: 83.03%





2025年5月26日 星期一

10. Regular Expression Matching

 10. Regular Expression Matching

難度: Hard
類型: String, Dynamic Programming, Recursion
CPP程式下載: 10_1.cpp 10_2.cpp 10_3.cpp 10_4.cpp

前情題要:
一個 source string, 一個 pattern string, 規則如下:
'.': 代表任一字元
'': 代表 0個到多個前一個字元。
如果 source string 可以符合 pattern string 的規則, 就回傳 true, 反之則回傳 false。
















思考方式:
1. 這邊的’*’, 與原本認知的"0個到多個任意符號", 並不相同。注意, 是"0個到多個的前一個符號"。譬如 "r*", 就是0到多個r。譬如 ".*" 才是0到多個任意符號。如果這邊沒有注意到, 會多走很多冤枉路。

2. 10_1.cpp 跟 10_2.cpp, 是不同時間寫出來的, 基本上 10_1.cpp 好一點點。10_2.cpp 是先找到 '*' 再回推, 所以計算上會稍稍多走一點冤枉路。不過差不太多, 10_1.cpp 最快花費869ms, 空間約10.2MB; 10_2.cpp 最快花費963ms, 空間約9.4MB。

3. 後來我發現 "isMatch(s.substr(j), p.substr(i+1))" 上。首先 substr 是會複製一個 string 出來, 而 isMatch 的輸入string, 是傳 string 實體, 而不是傳位置, 這代表每次 recursion 呼叫一次, 就複製一個新的 string 然後進到函數前再被複製一次。然而很多次 recursion 的呼叫累積下來, 浪費了很多時間。這邊要改。

4. 10_3.cpp 就是改了recusion 呼叫的函數, 改成傳 array pointer。很明顯的, 從結果來看, 時間上的花費從 869~1100ms 降到了526~550ms, 而空間上的花費從9.4MB降到了7.9MB~8.1MB。

5. 10_4.cpp, 與10_3.cpp相比則是優化了流程, 一邊找 '*' 的同時, 也一邊比較第 i-1或i-2 位置之前的char* p 與 char* s。這邊可以看到時間上優化有限, 進步到507~519ms, 而空間上沒差別, 也是 7.9MB~8.1MB。

到這邊先告一段落, 再來進步有限。有更好的方法歡迎留言討論~


複雜度思考:
Time: O ( N! )

Memory: O ((M+N+2)*sizeof(char))

結果:

636 / 636 testcases passed

Runtime: 507 ms, Beats: 7.43%

Memory: 7.92 MB, Beats: 94.83%