]Leetcode]-[Reorder List ]-三种解法

Given a singly linked list LL0→L1→…→Ln-1→Ln,
reorder it to: L0→LnL1→Ln-1→L2→Ln-2→…

You must do this in-place without altering the nodes‘ values.

For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.

题目的意思就是,给定一个链表,从两头开始链接,

比如1-2-3-4-5-6,最开始取两头,组成1-6,剩下2-3-4-5;

接着取两头,2-5,和上面的1-6连接起来,组成1-6-2-5,剩下3-4;

接着取两头, 3-4,同理和上面的结果连接起来,组成 1-6-2-5-3-4;

我一共做了3种解法:第一种解法,使用递归的解法,每次都取两头,然后递归的去解;一共递归n/2次,每次需要从头开始遍历到最后一个元素,需要n步,所以时间复杂度是O(N*N),, 空间复杂度O(1). 但是结果是超时了。。。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:

    ListNode *recurse(ListNode *head)
    {
        if(head == NULL || head->next == NULL)
        {
            return head;
        }
        ListNode *cur = head, *pre = head;
        while(cur->next != NULL)
        {
            pre = cur;
            cur = cur->next;
        }
        pre->next = NULL;
        ListNode *next = head->next;
        head->next = cur;
        cur->next = recurse(next);
        return head;
    }
    void reorderList(ListNode *head)
    {
        if(head == NULL || head->next == NULL)
            return;
        head =recurse(head);

    }
};

第二种解法,比较有效率,O(N)的时间复杂度,O(1)空间复杂度。思路是:将链表平均分为前后2段(l和r),将r倒转,然后按照顺序将l和r拼接起来。AC了

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:

ListNode *split(ListNode *head)
{
    ListNode *p = head;
    ListNode *q = head->next;
    while(q != NULL && q->next != NULL)
    {
        q = q->next->next;
        p = p->next;
    }
    q = p->next;
    p->next = NULL;
    return q;
}

ListNode *reverse(ListNode *head)
{
    if(head == NULL || head->next == NULL)
        return head;
    ListNode *pre = head, *cur = head->next, *next;
    head->next = NULL;
    while(cur != NULL)
    {
        next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}
void reorderList(ListNode *head)
{
    if(head == NULL || head->next == NULL)
        return;
    ListNode *r = reverse(split(head));
    ListNode *l = head->next;
    ListNode *traverse = head;
    while(r != NULL && l != NULL)
    {
        ListNode *tmp_r = r->next;
        ListNode *tmp_l = l->next;
        traverse->next = r;
        traverse = traverse->next;
        traverse->next = l;
        traverse = traverse->next;
        l = tmp_l;
        r = tmp_r;
    }
    if(r != NULL)
        traverse->next = r;
    else
        traverse->next = l;
}
};

最后一种解法是最直接的,借助了一个O(N)的空间,写起来比较简单,而且代码很容易懂,依然O(N)的时间复杂度,比第二种解法快了3ms。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:

void reorderList(ListNode *head)
{
    if(head == NULL || head->next == NULL)
        return;
    vector<ListNode *> vec;
    ListNode *p = head->next;
    while(p != NULL)
    {
        vec.push_back(p);
        p = p->next;
    }
    p = head;
    vector<ListNode *>::size_type i, j;
    for(i = 0, j = vec.size() - 1; i < j; i++, j--)
    {
        p->next = vec[j];
        p = p->next;
        p->next = vec[i];
        p = p->next;
    }
    if(i == j)
    {
        p->next = vec[i];
        p = p->next;
    }
    p->next = NULL;
}
};
时间: 2024-11-04 12:41:18

]Leetcode]-[Reorder List ]-三种解法的相关文章

[LeetCode] Remove Element (三种解法)

Given an array and a value, remove all instances of that value in place and return the new length. The order of elements can be changed. It doesn't matter what you leave beyond the new length. 这题做下来感觉技巧性比较强,解出第一种解法以后我又尝试了另外两种解法,一个比一个简单...我一开始却折腾出了最晦涩

LeetCode算法题-First Bad Version(Java实现-三种解法)

这是悦乐书的第200次更新,第210篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第66题(顺位题号是278).您是产品经理,目前领导团队开发新产品.不幸的是,您产品的最新版本未通过质量检查.由于每个版本都是基于以前的版本开发的,因此坏版本之后的所有版本也是坏的. 假设您有n个版本[1,2,...,n]并且您想找出第一个坏的版本,这会导致以下所有版本都不好.您将获得一个API bool isBadVersion(版本),它将返回版本是否错误. 实现一个函数来查找第一

LeetCode算法题-Move Zeroes(Java实现-三种解法)

这是悦乐书的第201次更新,第211篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第67题(顺位题号是283).给定一个数组nums,写一个函数将所有0移动到它的末尾,同时保持非零元素的相对顺序.例如: 输入:[0,1,0,3,12] 输出:[1,3,12,0,0] 注意: 您必须在不制作数组副本的情况下就地执行此操作. 最小化操作总数. 本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试. 02

UVALive 6257 Chemist&#39;s vows --一道题的三种解法(模拟,DFS,DP)

题意:给一个元素周期表的元素符号(114种),再给一个串,问这个串能否有这些元素符号组成(全为小写). 解法1:动态规划 定义:dp[i]表示到 i 这个字符为止,能否有元素周期表里的符号构成. 则有转移方程:dp[i] = (dp[i-1]&&f(i-1,1)) || (dp[i-2]&&f(i-2,2))     f(i,k):表示从i开始填入k个字符,这k个字符在不在元素周期表中.  dp[0] = 1 代码: //109ms 0KB #include <ios

最长单调递增子序列的三种解法

问题描述: 找出由n个数组成的序列的最长单调递增子序列 解法一:转化成LCS问题求解,时间复杂度为O(n*n). 思路:原序列为A,把A按升序排序得到序列B,求出A,B序列的最长公共子序列,即为A的最长单调递增子序列. #include<iostream> #include<algorithm> #include<string> #include<cstdio> using namespace std; //转化成LCS问题,时间复杂度O(n*n) int

C语言--求字符串长度的三种解法

问题: 求一个字符串的三种解法 一.计数的方法 #include<stdio.h> #include<assert.h> int my_strlen( char* str) { int count=0; while (*str) { count++; str++; } return count; } int main(void) { char *arr = "abcef"; int ret = my_strlen(arr); printf("%d\n&

Binary Tree Inorder Traversal [leetcode] 非递归的三种解法

第一种方法是Morris Traversal 是O(n)时间复杂度,且不需要额外空间的方法.缺点是需要修改树. 通过将叶子节点的right指向其中序后继. 代码如下 vector<int> inorderTraversal(TreeNode *root) { vector<int> res; TreeNode * cur = root; TreeNode * pre = NULL; while (cur) { if (cur->left == NULL) { res.push

数学奥林匹克问题解答:一道不等式题目的三种解法

设 $a_1, a_2, \cdots, a_n\in\mathbf{N^*}$, 且各不相同. 求证: $${a_1\over1^2} + {a_2\over2^2} + \cdot + {a_n\over n^2} \ge {1\over1} + {1\over2} + \cdots + {1\over n}.$$ 解法一: 考虑使用基本不等式 $a + b\ge 2\sqrt{ab}$ 消去左边各项之分子. $$\because {a_k\over 1^2} + {1\over a_k}

跳台阶问题(变态跳台阶)的三种解法

题目1:一个台阶总共有n级,如果一次可以跳1级,也可以跳2级.求总共有多少总跳法,并分析算法的时间复杂度. 们把n级台阶时的跳法看成是n的函数,记为f(n).当n>2时,第一次跳的时候就有两种不同的选择:一是第一次只跳1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1):另外一种选择是第一次跳2级,此时跳法数目等于后面剩下的n-2级台阶的跳法数目,即为f(n-2).因此n级台阶时的不同跳法的总数f(n)=f(n-1)+(f-2). 我们把上面的分析用一个公式总结如下: /