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
思路:用栈,这样如果两个链表长度不相等的时候不用那么麻烦。
难点在于代码的细节控制。
- 当代码中出现空栈时候,则对应的数置为0,不要再写if判断了。
- 用第三个栈重建一个链表,这样耗费空间。可以参考第一种写法,总之这道题在于细节控制,思想上不难。
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;
}