leetcode刷题详解三

2. 两数相加

思路:直接加,注意进位条件不要用if,核心代码在于sum = l1->val + l2->val + carry;

c++ 复制代码
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* dummy = new ListNode();
        ListNode* dummy_head = dummy;
        int carry = 0;
        int sum = 0;
        int single = 0;
        while(l1 && l2){
            sum = l1->val + l2->val + carry;
            carry = sum / 10;
            single = sum % 10;
            ListNode* node = new ListNode(single);
            dummy -> next = node;
            dummy = dummy->next;
            l1 = l1->next;
            l2 = l2->next;
        }
        while(l1){
            sum = l1->val + carry;
            carry = sum / 10;
            single = sum % 10;
            ListNode* node = new ListNode(single);
            dummy -> next = node;
            dummy = dummy->next;
            l1 = l1->next;
        }
        while(l2){
            sum = l2->val + carry;
            carry = sum / 10;
            single = sum % 10;
            ListNode* node = new ListNode(single);
            dummy -> next = node;
            dummy = dummy->next;
            l2 = l2->next;
        }
        if(carry){
            ListNode* node = new ListNode(carry);
            dummy -> next = node;
            dummy = dummy->next;
        }
        return dummy_head->next;
    }
445. 两数相加 II

思路:用栈,这样如果两个链表长度不相等的时候不用那么麻烦。

难点在于代码的细节控制。

  1. 当代码中出现空栈时候,则对应的数置为0,不要再写if判断了。
  2. 用第三个栈重建一个链表,这样耗费空间。可以参考第一种写法,总之这道题在于细节控制,思想上不难。
c++ 复制代码
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        stack<int> s1;
        stack<int> s2;
        int carry = 0;
        int sum = 0;
        int single = 0;
        ListNode* dummy = new ListNode();
        ListNode* dummy_head = dummy;

        while(l1){
            s1.push(l1->val);
            l1=l1->next;
        }
        while(l2){
            s2.push(l2->val);
            l2 = l2->next;
        }
        
        while(!s1.empty() && !s2.empty()){
            sum  = s1.top() + s2.top() + carry;
            single = sum % 10;
            carry = sum / 10;
            ListNode * tmp = new ListNode(single);
            dummy -> next = tmp;
            dummy = dummy->next;
            s1.pop();
            s2.pop();
        }
        while(!s1.empty()){
            sum  = s1.top() + carry;
            single = sum % 10;
            carry = sum / 10;
            ListNode * tmp = new ListNode(single);
            dummy -> next = tmp;
            dummy = dummy->next;
            s1.pop();
        }
        while(!s2.empty()){
            sum  = s2.top() + carry;
            single = sum % 10;
            carry = sum / 10;
            ListNode * tmp = new ListNode(single);
            dummy -> next = tmp;
            dummy = dummy->next;
            s2.pop();
        }
        if(carry){
            ListNode * tmp = new ListNode(carry);
            dummy -> next = tmp;
            dummy = dummy->next;
        }

        ListNode* reverse_head = reverse(dummy_head->next);
        return reverse_head;
    }

    ListNode* reverse(ListNode* node){
        if(!node || !node->next){
            return node;
        }
        ListNode* tmp = reverse(node->next);
        node->next->next = node;
        node->next = nullptr;
        return tmp;
    }
725. 分隔链表

思路:这道题就是先求出链表长度,然后分段。

主要难点在于断链,vector每一个索引都是一个链表,在锻炼表操作这里我足足困了好长时间

其实重点就两句话:dummy = root;

root = root->next;(这个代码是设置前置节点的最好办法)

因为我们要找到前置节点,其实很简单dummy = root 中dummy就可以变成前置节点了!!!

c++ 复制代码
vector<ListNode*> splitListToParts(ListNode* root, int k) {        
    //计算长度        
    int length = 0;        
    ListNode* temp = root;        
    while(temp){            
        length++;            
        temp = temp->next;        
    }        
    //每个断链的长度        
    int arry_len = (length / k) > 0 ? (length / k) : 1;        
    int arry[k];        
    for(int i = 0;i < k; i++){            
        arry[i] = arry_len;        
    }        
    //因为长度差不超过一,因此根据length和k*arry_len的差依次给前面的每个值+1        
    int gap = 0;        
    if((k * arry_len) < length){            
        gap = length - (k * arry_len);            
        for(int i = 0;i < gap;i++){                
            arry[i]++;            
        }        
    }                
    //断链表操作        
    vector<ListNode*> splict;        
    ListNode* dummy ;        
    for(int i = 0; i < k; i++){            
        splict.push_back(root);            
        for(int j = 0;j < arry[i];j++){                
            if(root){                    
                dummy = root;/*前置结点的精髓所在*/                    
                root = root->next;                
            }                          
        }
        if(dummy){                    
             dummy->next = NULL;                
        }  
    }        
    return splict;    
}
328. 奇偶链表

双指针然后拼接

c++ 复制代码
ListNode* oddEvenList(ListNode* head) {
    if(!head || !head->next || !head->next->next){
        return head;
    }
    ListNode* odd = head;
    ListNode* even = head->next;
    ListNode* dummy = even;
    while(odd->next && even->next){
        odd->next = even->next;
        odd = odd->next;
        even->next = odd->next;
        even = even->next;
    }
    odd->next = dummy;
    return head;
}
⭕️92. 反转链表 II

反转链表精髓:

关于反转链表相关的递归思想,看这个

这个反转链表,思想和反转前n个链表一模一样。

只不过,第一个left不是从1开始反转,那又如何?我们可以让他变成从1开始,想一想。

反转前n个链表

c++ 复制代码
ListNode* temp = nullptr;
    ListNode* reverseN(int n,ListNode* node){
        if(n == 1){
            temp = node->next;
            return node;
        }

        ListNode* last = reverseN(n-1, node->next);
        node->next->next = node;
        node->next = temp;
        return last;
    }

这道题解,递归解法----反转链表递归解法还是比较简单的

c++ 复制代码
ListNode* reverseBetween(ListNode* head, int left, int right) {
        ListNode* dummy = head;
        ListNode* n1 = nullptr;
        int length = right - left +1;
        while(left > 1){
            n1 = dummy;/*记录前一个节点*/
            dummy = dummy->next;
            left--;
        }
        ListNode* n2 = reverseN(length, dummy);
    	//n1为空说明left就是1,从第一个位置反转的!!!
        if(n1){
            n1->next = n2;
        }else{
            return n2;
        }
        return head;
    }

    ListNode* temp = nullptr;
    ListNode* reverseN(int n,ListNode* node){
        if(n == 1){
            temp = node->next;
            return node;
        }

        ListNode* last = reverseN(n-1, node->next);
        node->next->next = node;
        node->next = temp;
        return last;
    }

/*******************第二种解法***********************/
/*有两个dummy节点,begin前和end后,因此要判断四次*/
ListNode* reverseBetween(ListNode* head, int left, int right) {
    if(!head || !head->next){
        return head;
    }
    ListNode* begin = head;
    ListNode* end = head;
    ListNode* dummy = nullptr;
    while(left > 1){
        dummy = begin;
        begin = begin->next;
        left--;
    }
    while(right > 1){
        end = end->next;
        right--;
    }
    ListNode* dummy2 = end->next;
    ListNode* node = reverse(begin, end);
    if(!dummy && !dummy2){
        cout<<"1"<<endl;
        return end;
    }
    else if(!dummy && dummy2){
        cout<<"2"<<endl;
        begin->next = dummy2;
        return end;
    }
    else if(dummy && !dummy2){
        cout<<"3"<<endl;
        dummy->next = end;
        return head;
    }
    cout<<"4"<<endl;
    dummy->next = node;
    begin->next = dummy2;
    return head;
}

ListNode* reverse(ListNode* begin, ListNode* end){
    if(begin == end){
        return begin;
    }
    ListNode* tmp = reverse(begin->next, end);
    begin->next->next = begin;
    begin->next = nullptr;
    return tmp;
}
83. 删除排序链表中的重复元素

思路如图所示,很好理解。

c++ 复制代码
ListNode* deleteDuplicates(ListNode* head) {
        if(!head || !head->next){
            return head;
        }
        int value = head->val;
        ListNode* temp = head->next;
        ListNode* carry = head;
        while(temp){
            if(temp->val == value){
                ListNode* dummy = temp;
                temp = temp->next;
                carry->next = temp;
                delete dummy;
                dummy = nullptr;
            }else{
                carry = carry->next;
                value = carry->val;
                temp = temp->next;
            }
        }
        return head;
    }
相关推荐
花嫁代二娃7 分钟前
Linux:计算机的层状结构
linux·操作系统
路飞雪吖~9 分钟前
【Linux】共享内存
java·linux·服务器
maomi_95261 小时前
操作系统之EXT文件系统
linux·服务器
伤不起bb4 小时前
MySQL 高可用
linux·运维·数据库·mysql·安全·高可用
远瞻。4 小时前
【论文阅读】人脸修复(face restoration ) 不同先验代表算法整理2
论文阅读·算法
先做个垃圾出来………7 小时前
哈夫曼树(Huffman Tree)
数据结构·算法
tmacfrank7 小时前
网络编程中的直接内存与零拷贝
java·linux·网络
phoenix@Capricornus9 小时前
反向传播算法——矩阵形式递推公式——ReLU传递函数
算法·机器学习·矩阵
Inverse1629 小时前
C语言_动态内存管理
c语言·数据结构·算法
数据与人工智能律师9 小时前
虚拟主播肖像权保护,数字时代的法律博弈
大数据·网络·人工智能·算法·区块链