5.4算法题

重排链表(力扣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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值