重排链表(力扣143.)
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思考:
用链表左半端与反转后的右半端进行合并,合并后的结果即为重排的链表。
代码:
链表中点+反转链表+合并链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){//反转链表
struct ListNode* prev = NULL;
struct ListNode* curr = head;
while(curr)
{
struct ListNode* next = curr -> next;
curr -> next = prev;
prev = curr;
curr = next;
}
return prev;
}
struct ListNode* middleNode(struct ListNode* head){//找到中点
if(head == NULL || head -> next == NULL) {
return head;
}
struct ListNode* fast = head, *slow = head;
while(fast != NULL && fast -> next != NULL) {
slow = slow -> next;
fast = fast -> next -> next;
}
return slow;
}
void mergeList(struct ListNode* l1, struct ListNode* l2) {//合并链表
struct ListNode* p, * q;
while(l1 != NULL && l2 != NULL) {
p = l1 -> next;
q = l2 -> next;
l1 -> next = l2;
l1 = p;
l2 -> next = l1;
l2 = q;
}
}
void reorderList(struct ListNode* head) {
if (head == NULL) {
return;
}
struct ListNode* mid = middleNode(head);
struct ListNode* l1 = head;
struct ListNode* l2 = mid->next;
mid->next = NULL;//将左半部分与右半部分断开
l2 = reverseList(l2);//反转
mergeList(l1, l2);//合并
}
两数之和 II - 输入有序数组:
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
思考:
考虑到给定数组是有序的,我们可以用双指针的思路来进行查找。
当首尾两项和大于target时,right–;
当首尾两项和小于target时,left++。
用这种办法逐步逼近,相比于双层遍历的解法快了不少。
头部注释表明必须用malloc函数申请返回数组的空间
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* numbers, int numbersSize, int target, int* returnSize){
int *ret = (int* )malloc(sizeof(int)*2);
*returnSize = 2;//按头部注释的方式来
int left = 0,right = numbersSize - 1;//初始化,从首尾开始,逐步向中间逼近
while(left < right) {
if(numbers[left] + numbers[right] == target) {
ret[0] = left + 1; ret[1] = right + 1;
return ret;
} else if(numbers[left] + numbers[right] > target) {
right--;
continue;
} else{
left++;
continue;
}
}
ret[0] = -1; ret[1] = -1;//循环结束仍没有return,直接返回-1
return ret;
}