笔试面试题总结之单链表(Linked List)

引言

链表是最常用且最简单的一种数据结构,而且由于依赖指针进行操作,所以在笔试面试题中大量出现,一方面考察对于单链表的各项操作,另一方面也考察对于指针操作的熟练程度。题目中一般涉及到的链表均为单链表,因此总结的大部分操作也是以单链表为主。
此总结为刷完LeetCode中标签为Linked List的题之后写的,所以涉及的操作和题目均与LeetCode有关,欢迎访问我的LeetCode题解交流学习。

一、链表的基本操作

链表的基本操作包括新建结点、构造链表、删除结点、打印链表、清空链表等一系列操作,但这里只讨论笔试题中需要用到的部分操作,列出的下述操作均为提交链表相关题目之前自己在IDE中测试时需要用到的。

单链表结点结构

单链表中的数据用结点来表示,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。结点结构如下:

struct ListNode
{
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL){}
};

第5行是一个含有初值的构造函数,用来给新建结点赋值并将其指针域置空。

构造链表

链表的构造有两种方法:头插法和尾插法,头插法构造的链表跟数据输入顺序相反,尾插法构造的链表保留了输入顺序。构造方法如下:

ListNode* CreateListFromHead(ListNode *head, int val) // 头插法构造链表
{
    ListNode *node = new ListNode(val);
    node->next = head;
    head = node;
    return head;
}
ListNode* CreateListFromTail(ListNode *head, int val) // 尾插法构造链表
{
    ListNode *curr = head;
    ListNode *node = new ListNode(val);
    if (head == NULL)
        head = node;
    else
    {
        while (curr->next)      // curr指向尾结点
            curr = curr->next; 
        currPtr->next = node;
    }
    return head;
}

我们用到的链表均不包含头结点(即head指针直接指向链表的第一个结点)。

打印链表

打印链表操作用来检查链表的构造以及显示在各种操作中链表的变化,如下所示:

void PrintList(ListNode *head) // 打印链表
{
    if (!head)
        return;
    ListNode *curr = head;
    while (curr->next != NULL)
    {
        cout << curr->val << "->";
        curr = curr->next;
    }
    cout << curr->val << endl;
}

打印操作输出链表中所有结点val值,中间用“->”连接。

清空链表

在做题过程中,需要输入多组测试数据,因此需要对上次链表进行清空操作,如下所示:

ListNode* freeList(ListNode *head) // 清空链表
{
    ListNode *curr = NULL;
    while (head)
    {
        curr = head->next;
        delete head;
        head = curr;
    }
    return head;
}

清空链表操作删除所有结点并释放结点空间,返回空指针。

二、LeetCode上关于linked list题解

众所周知,LeetCode是找工作前必刷的题库,因此接下来针对LeetCode上跟链表相关的题目对链表操作进行描述。
前期刷题时不必直接手写代码,可以自行在本地IDE编译测试,因此这里提供一个大部分题目都要用到的代码模板,基本上包括了上面所有的链表基本操作。

#include <iostream>
#include <fstream>
#include <ctime>
#include <climits>
#include <vector>

using namespace std;

/* 链表结点 */
struct ListNode
{
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL){}
};

/* 打印链表 */
void PrintList(ListNode *head)
{
    if (!head)
        return;
    ListNode *currPtr = head;
    while (currPtr->next != NULL)
    {
        cout << currPtr->val << "->";
        currPtr = currPtr->next;
    }
    cout << currPtr->val << endl;
}

/* 构造链表(头插法)*/
ListNode* CreateListFromHead(ListNode *head, int val)
{
    ListNode *node = new ListNode(val);
    node->next = head;
    head = node;
    return head;
}

/* 构造链表(尾插法)*/
ListNode* CreateList(ListNode *head, int val)
{
    ListNode *currPtr = head;
    ListNode *node = new ListNode(val);
    if (head == NULL)
        head = node;
    else
    {
        while (currPtr->next)
            currPtr = currPtr->next;
        currPtr->next = node;
    }
    return head;
}

/* 清空链表 */
ListNode* freeList(ListNode *head)
{
    ListNode *currPtr = NULL;
    while (head)
    {
        currPtr = head->next;
        delete head;
        head = currPtr;
    }
    return head;
}

int main()
{
    streambuf *readbuf = cin.rdbuf();
    streambuf *writebuf = cout.rdbuf();

    ifstream fin;
    ofstream fout;

    fin.open("data.in");
    fout.open("data.out");

    cin.rdbuf(fin.rdbuf());
    cout.rdbuf(fout.rdbuf());

    clock_t startTime, endTime;

    ListNode *head = NULL;
    int n; // 链表长度
    int val; // 结点值
    while (cin >> n) // 多组测试数据
    {
        for (int i = 0; i < n; i++) // 输入结点值,创建链表
        {
            cin >> val;
            head = CreateList(head, val);
        }
        cout << "original list: "; // 打印原链表
        PrintList(head);

        startTime = clock();


        /**********************************************************************/
        // 调用你的处理函数
        // head = yourfun(head);
        cout << "     new list: ";
        PrintList(head); // 打印处理后的链表

        /**********************************************************************/

        endTime = clock();
        cout << "      runtime: " << (double)(endTime - startTime) / CLOCKS_PER_SEC * 1000 << "ms" << endl;
        head = freeList(head); // 清空链表,接收再次测试
    }

    cin.rdbuf(readbuf);
    cout.rdbuf(writebuf);

    fin.close();
    fout.close();

    return 0;
}

上述 代码将标准输入输出重定向到了文件中,方便多次多组测试,因此需要创建一个data.in文件用于数据输入,创建data.out文件用于数据输出,数据输入格式定义为第一行输入整数N表示结点的个数(输入非数字字符结束测试),接着一行输入N个整数表示结点值,输入示例如下:

2
1 2
5
5 4 3 2 1
10
4 6 3 8 0 2 9 7 1 5
q

上述代码可以直接执行,当需要测试时,只需在其中添加自己的处理函数,然后在main函数中调用处理函数,即可进行测试,下面的各种函数均基于上述方式进行调试、测试。

说明

LeetCode中 Linked List标签下截止目前(2017/09/20)共有27道题目,除了需要付费的369、379以及跟BST相关的109,总共24道题,我把它们分成了五类:

类别题号
删除相关操作237/203/83/82/19
反转相关操作206/92/61/24/25
排序相关操作86/21/143/147/148/23
环相关操作141/160/138/142
其他相关操作234/2/445/328

下面将详细介绍比较有代表性的一些题目,大家可以到这里这里这里查看所有题目的分析和代码。

删除相关操作

237. Delete Node in a Linked List

题目描述:
Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.

Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.

分析题解:
这就是一个简单的删除给定结点的题。AC代码(Runtime: 19ms):

void deleteNode(ListNode* node) {
        if(node == NULL || node->next == NULL)
            return;
        node->val = node->next->val;
        node->next = node->next->next;
    }

203. Remove Linked List Elements

题目描述:

Remove all elements from a linked list of integers that have value val.

Example
Given: 1 –> 2 –> 6 –> 3 –> 4 –> 5 –> 6, val = 6
Return: 1 –> 2 –> 3 –> 4 –> 5

分析题解:
删除值等于给定val的结点,遍历删除即可,但要注意头结点和尾结点的删除以及结点空间的合理释放。鉴于比较简单,就不放代码了,到这里这里这里查看代码哈。

83. Remove Duplicates from Sorted List

题目描述:
Given a sorted linked list, delete all duplicates such that each element appear only once.

For example,
Given 1->1->2, return 1->2.
Given 1->1->2->3->3, return 1->2->3.

分析题解:
对于重复结点,删除多余的保留一个。用两个指针一前一后来遍历,若值相等,则把前指针指向后指针的next就可以了。
AC代码(Runtime: 13ms):

ListNode* deleteDuplicates(ListNode* head) {
        if(!head)
            return head;
        ListNode *currPtr = head->next; 
        ListNode *prevPtr = head;       
        while(currPtr)
        {
            if(currPtr->val == prevPtr->val)
                prevPtr->next = currPtr->next;
            else
                prevPtr = currPtr;
            currPtr = currPtr->next;
        }
        return head;
    }

82. Remove Duplicates from Sorted List II

题目描述:
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.

分析题解:
用head->next->val值作为标志来删除所有val值相同的结点,可以保证删除所有的相同的结点,AC代码(Runtime: 6ms):

ListNode* deleteDuplicates(ListNode* head) {
    if (!head || !head->next) 
        return head;
    ListNode dummy(0);
    ListNode *prev = &dummy;
    dummy.next = head;
    int val = head->next->val; // val值用来表示当前扫描节点的下一结点值
    while (head)
    {
        if (head->val == val)
        {
            while (head && head->val == val) // 如果存在相同结点,则一直扫描到下一val值结点
                head = head->next;
            prev->next = head;
            if (head && head->next) // 
                val = head->next->val;
            else
                break;
        }
        else
        {
            prev = head;
            head = head->next;
            //val = head->next ? head->next->val : 0;
            if (head->next)
                val = head->next->val;
            else
                break;
        }
    }
    return dummy.next;
}

19. Remove Nth Node From End of List

题目描述:
Given a linked list, remove the nth node from the end of list and return its head.

For example,

Given linked list: 1->2->3->4->5, and n = 2.

After removing the second node from the end, the linked list becomes 1->2->3->5.

Note:
Given n will always be valid.
Try to do this in one pass.

分析题解:
删除倒数第N个结点,N保证合法,但题目要求“in one pass”即一次扫描完成,可以使用两个指针,一前一后,前指针先扫描N步,然后两个指针一起走,当前指针走到尾结点,则后指针走到要删除结点的前一结点。AC代码(Runtime: 6ms):

ListNode* removeNthFromEnd(ListNode* head, int n) {
    ListNode *front = head, *rear = head; 
    while (n--) front = front->next;      
    if (!front) return head->next;        
    while (front->next)                  
    {
        rear = rear->next;
        front = front->next;
    }
    rear->next = rear->next ? rear->next->next : NULL; // delete that node
    return head;
}

反转相关操作

206. Reverse Linked List

题目描述:
Reverse a singly linked list.

分析题解:
反转链表,这算是链表的基本操作,是面试官很喜欢考的基础,有迭代和递归两种方式。AC代码(Runtime: 6ms(递归)/ 9ms(迭代)):

ListNode * reverseList(ListNode * head) // 迭代
{
    ListNode *p = NULL, *q;
    while (head)
    {
        q = head->next;
        head->next = p;
        p = head;
        head = q;
    }
    return p;
}

ListNode * reverseList(ListNode * head) // 递归
{
    if (head == NULL || head->next == NULL)
        return head;
    ListNode *h = reverseList(head->next);
    head->next->next = head;
    head->next = NULL;
    return h;
}

92. Reverse Linked List II

题目描述:
Reverse a linked list from position m to n. Do it in-place and in one-pass.

For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,

return 1->4->3->2->5->NULL.

Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.

分析题解:
反转序号m、n之间的链表,核心还是反转链表,只是需要先走到m结点。AC代码(Runtime: 3ms):

ListNode* reverseBetween(ListNode* head, int m, int n) {
       ListNode dummy(0);
    ListNode *pre = &dummy;
    pre->next = head;
    for (int i = 1; i < m; i++)
        pre = pre->next;
    ListNode *move, *curr = pre->next;
    for (int j = 0; j < n - m; j++)
    {
        move = curr->next;
        curr->next = move->next;
        move->next = pre->next;
        pre->next = move;
    }
    return dummy.next;
    }

61. Rotate List

题目描述:
Given a list, rotate the list to the right by k places, where k is non-negative.

For example:
Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.

分析题解:
题目要求从头开始,翻转接下来的K个结点。用front/rear两个指针,先让front向前扫描K个结点,然后两个指针一起扫描直到front到链表末尾此时rear指针即为新链表的尾结点,rear->next为新链表的头结点。题中K值可能非常大,所以不能直接用,必须先得到链表长度len,K = K % len,不然会超时。AC代码(Runtime: 15ms):

ListNode* rotateRight(ListNode* head, int k) {
        if (!head || !head->next)
        return head;
    int length = 1;
    ListNode *curr = head;
    while(curr = curr->next) // 获取链表长度
        ++length;
    k = k % length;
    ListNode *front = head;
    ListNode *rear = head;
    while (front && k--) // 前指针先行k步
        front = front->next;
    if (!front) // 走到链表尾说明k等于链表长,返回原链表
        return head;
    while (front->next) // 前后指针一起走直到前指针走到尾
    {
        rear = rear->next;
        front = front->next;
    }
    front->next = head; // 转接两部分
    head = rear->next;
    rear->next = NULL;
    return head;
    }

24. Swap Nodes in Pairs

题目描述:
Given a linked list, swap every two adjacent nodes and return its head.

For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.

Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

分析题解:
题目要求交换相邻的两个结点,不能改变 结点的值,而且不能用太多额外空间。我的选择是把相邻的结点反转,再拼接到新链表上。AC代码(Runtime: 3ms):

ListNode* swapNode(ListNode *head) // p->q改成q->p
{
    if (head->next)
    {
        head->next->next = head;
        head = head->next;
        head->next->next = NULL;
    }
    return head;
}

ListNode* swapPairs(ListNode* head) { 
    if (!head || !head->next)
        return head;
    ListNode *currPtr = head;
    ListNode *temp = NULL;
    head = NULL;
    ListNode dummy(0);
    ListNode *tail = &dummy;
    while (currPtr && currPtr->next)
    {
        temp = currPtr;
        currPtr = currPtr->next->next;
        temp->next->next = NULL;
        if (!head)
        {
            head = swapNode(temp);
            tail = head->next;
        }
        else
        {
            tail->next = swapNode(temp);
            tail = temp->next ? temp->next : temp;
        }
    }
    if (currPtr)
        tail->next = currPtr;
    return head;
}

25. Reverse Nodes in k-Group

题目描述:
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

You may not alter the values in the nodes, only nodes itself may be changed.

Only constant memory is allowed.

For example,
Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

分析题解:
其实这就是一个带前驱结点的反转链表题,核心就是反转链表,注意处理最后不满K的结点就好了。AC代码(Runtime: 28ms):

ListNode* reverseKGroup(ListNode* head, int k) {
    if (!head || !head->next)
        return head;
    ListNode dummy(0);
    ListNode *prev = &dummy;
    dummy.next = head;
    ListNode *curr = prev;
    int length = 0;
    while (curr = curr->next) // get length of list
        ++length;
    while (length >= k)
    {
        curr = prev->next;
        for (int i = 1; i < k; i++)
        {
            ListNode *temp = curr->next;
            curr->next = temp->next;
            temp->next = prev->next;
            prev->next = temp;
        }
        prev = curr;
        length -= k;
    }

    return dummy.next;
}

排序相关操作

86. Partition List

题目描述:
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.

分析题解:
题目要求把把链表根据val值重新构造成前面小于x后面>=x的形式,我的选择是扫描链表,分别将将值小于X和大于等于X的结点连成两个链表,最后再将两个链表拼接成一个链表。AC代码(Runtime:6ms):

ListNode* partition(ListNode* head, int x) {
     ListNode left(0), right(0);
    ListNode *lptr = &left, *rptr = &right;

    while (head){
        ListNode* &ref = head->val < x ? lptr : rptr; // 这里必须用引用
        ref->next = head;
        ref = ref->next;

        head = head->next;
    }
    lptr->next = right.next; // 重新拼接
    rptr->next = NULL;
    return left.next;
    }

143. Reorder List

题目描述:
Given a singly linked list L: L0?L1?…?Ln-1?Ln,
reorder it to: L0?Ln?L1?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}.

分析题解:
根据题目要求,找到中间结点,反转后半部分,再交叉插入构造新链表即可。AC代码(Runtime:66ms):

ListNode* ReverseList(ListNode *head) /* 反转链表 */
{
    ListNode *p = head;
    ListNode *q = p->next;
    head->next = NULL;
    while(q)
    {
        p = q;
        q = q->next;
        p->next = head;
        head = p;
    }
    return head;
}

ListNode* MergeList(ListNode *left, ListNode *right) /* 交叉合并两个排好序链表 */
{
    ListNode *head = left;
    left = left->next;
    ListNode *tail = head;
    bool leftNode = false;
    while(left || right)
    {
        ListNode *&temp = leftNode ? left : right;
        tail->next = temp;
        tail = temp;
        temp = temp->next;
        leftNode = leftNode ? false : true;
    }
    return head;
}

/* Reorder List */
void reorderList(ListNode *head)
{
    if(!head || !head->next)
        return;
    // 快慢指针找到链表中间结点 中间结点的下一结点为新链表的尾结点
    ListNode *low = head;
    ListNode *fast = head;
    while(fast->next && fast->next->next)
    {
        fast = fast->next->next;
        low = low->next;
    }
    fast = low->next;
    low->next = NULL;
    fast = ReverseList(fast); // 翻转右半部分
    head = MergeList(head, fast); // 依次合并
}

148. Sort List

题目描述:
Sort a linked list in O(n log n) time using constant space complexity.

分析题解:
题目要求O(n log n)的时间复杂度,备选排序算法为快速排序、堆排序和归并排序,快排最差会达到O(n^2),所以排除,堆排序显然不适用单链表的结构,归并排序才是符合要求的排序算法,对于空间复杂度,因为结构为链表,所以用指针即可,不用像数组那样单独开辟空间,所以此题选用归并排序。AC代码(Runtime: 49ms):

ListNode* mergeList(ListNode *left, ListNode *right)
{
    ListNode temp(0);
    ListNode *tail = &temp;
    while(left && right) // 进行归并操作直至其中一个链表为空
    {
        ListNode *&temp = left->val <= right->val ? left : right; // 带等号保证序列的稳定性
        tail->next = temp;
        temp = temp->next;
        tail = tail->next;
    }
    if(left) tail->next = left; 
    if(right) tail->next = right;

    return temp.next;
}

ListNode* sortList(ListNode *head)
{
    if(head == NULL || head->next == NULL)
        return head;
    ListNode *low = head; // 快慢指针找到链表中点
    ListNode *fast = head;
    while(fast->next && fast->next->next)
    {
        low = low->next;
        fast = fast->next->next;
    }
    fast = low->next;  // 链表拆成两半
    low->next = NULL;
    ListNode *left = sortList(head); // 左右链表分别排序
    ListNode *right = sortList(fast);
    return mergeList(left, right); // 合并
}

23. Merge k Sorted Lists

题目描述:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

分析题解:
依次merge两个链表,递归调用直至所有链表有序。AC代码(Runtime: 276ms):

ListNode* mergeTwoLists(ListNode *head1, ListNode *head2)
{
    ListNode dummy(0);
    ListNode *newhead = &dummy;
    while (head1 && head2)
    {
        ListNode *& temp = head1->val <= head2->val ? head1 : head2;
        newhead->next = temp;
        newhead = temp;
        temp = temp->next;
    }
    if (head1)
        newhead->next = head1;
    if (head2)
        newhead->next = head2;
    return dummy.next;
}

ListNode* mergeKLists(vector<ListNode*>& lists) {
    ListNode *head = NULL;
    if (lists.size() == 0) return NULL;
    if (lists.size() == 1)
        return lists.at(0);
    else
    {
        head = lists.back();
        lists.pop_back();
        ListNode *head2 = mergeKLists(lists);
        head = mergeTwoLists(head, head2);
    }
    return head;
}

环相关操作

142. Linked List Cycle II

题目描述:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?

分析题解:
题目要求找出链表环开始的结点,首先用快慢指针判断是否有环,然后当快慢指针重合时,另快指针指向头结点,两个指针同步扫描,再次相遇的结点即为所求结点。AC代码(Runtime:9ms):

/* 判断链表是否有环 */
bool hasCycle(ListNode *head) {
    if (!head || !head->next)
        return false;
    ListNode *fast = head;
    ListNode *low = head;

    while (fast->next && fast->next->next)
    {
        fast = fast->next->next;
        low = low->next;
        if (fast == low)
            return true;
    }
    return false;
}

/* 寻找链表产生环的结点 */
ListNode *detectCycle(ListNode *head)
{
    if (!hasCycle(head))
        return NULL;
    ListNode *fast = head->next->next;
    ListNode *low = head->next;

    while (fast != low)
    {
        fast = fast->next->next;
        low = low->next;
    }
    fast = head;
    while (fast != low)
    {
        fast = fast->next;
        low = low->next;
    }

    return fast;
}

138. Copy List with Random Pointer

题目描述:
A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

分析题解:
在原链表的每个节点之后插入一个新的节点,这样原节点与新节点的对应关系就已经明确了,因此不需要用hash_map保存,但是需要第三次循环将整个链表拆分成两个。这种方法的时间复杂度是O(n),空间复杂度是O(1),网上还有用哈希表的方法自行查找。AC代码(Runtime:79ms):

RandomListNode *copyRandomList(RandomListNode *head) {
    /* newList表示新链表 curr代表原链表当前结点 newNode代表当前结点后的新结点 */
    RandomListNode *newList, *curr, *newNode;
    if (!head)
        return NULL;
    /* step1:在链表中每个节点后插入新结点 */
    for (curr = head; curr != NULL; curr = curr->next->next)
    {
        newNode = new RandomListNode(curr->label);
        newNode->next = curr->next;
        curr->next = newNode;
    }

    /* step2:根据原结点的random指针给新结点的random指针赋值 */
    for (curr = head; curr != NULL; curr = curr->next->next)
        curr->next->random = curr->random ? curr->random->next : NULL;

    /* step3:将链表拆分 */
    newList = head->next;
    for (curr = head; curr != NULL; curr = curr->next)
    {
        RandomListNode *tail = curr->next;
        curr->next = tail->next;
        if (tail->next)
            tail->next = tail->next->next;
    }
    return newList;
}

其他相关操作

445. Add Two Numbers II

题目描述:
You are given two non-empty linked lists representing two non-negative integers. The most significant digit comes first and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Follow up:
What if you cannot modify the input lists? In other words, reversing the lists is not allowed.

分析题解:
用链表表示的数字相加,逆置链表可以完成,不过要认真考虑进位和新加结点的问题。AC代码(Runtime:46ms):

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
       if (l1 == NULL)
        return l2;
    if (l2 == NULL)
        return l1;

    // l1 l2反转
    l1 = reverseList(l1);
    l2 = reverseList(l2);

    int flag = 0; // 进位
    int sum = 0;

    ListNode * newList = NULL;
    ListNode * currPtrNew = new ListNode(0);
    newList = currPtrNew;
    ListNode * newNode;

    while (l1 != NULL || l2 != NULL)
    {
        int a = l1 == NULL ? 0 : l1->val;
        int b = l2 == NULL ? 0 : l2->val;
        sum = a + b + flag;
        flag = sum / 10;
        newNode = new ListNode(sum % 10);
        currPtrNew->next = newNode;
        currPtrNew = newNode;

        l1 = l1 == NULL ? NULL : l1->next;
        l2 = l2 == NULL ? NULL : l2->next;
    }

    if (flag == 1)
    {
        newNode = new ListNode(flag);
        currPtrNew->next = newNode;
    }
    return reverseList(newList->next);
    }
    ListNode* reverseList(ListNode * & l)
{
        if(l->next == NULL)
            return l;
    ListNode *p, *q;
    p = l;
    q = p->next;
    p->next = NULL;
    while (q != NULL)
    {
        p = q;
        q = q->next;
        p->next = l;
        l = p;
    }
    return l;
}

328. Odd Even Linked List

题目描述:
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes.

You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity.

Example:
Given 1->2->3->4->5->NULL,
return 1->3->5->2->4->NULL.

分析题解:
题目要求将奇序号的结点全部提到前面。逻辑挺简单,直接贴AC代码(Runtime:16ms):

ListNode* oddEvenList(ListNode* head) {
        if (head == NULL || head->next == NULL)
        return head;
    ListNode *currPtr = head->next, *prevPtr = head; // 遍历结点、前一结点(从head->next开始)
    ListNode *oddNode, *oddListTail = head; // odd尾结点
    int i = 2; // 序号
    while (currPtr != NULL)
    {
        if (i % 2 == 1)
        {
            oddNode = currPtr;
            prevPtr->next = currPtr->next;
            currPtr = currPtr->next;
            oddNode->next = oddListTail->next;
            oddListTail->next = oddNode;
            oddListTail = oddNode;
        }
        else
        {
            prevPtr = currPtr;
            currPtr = currPtr->next;
        }
        ++i;
    }
    return head;
    }

总结

这些题解都是个人思考个人实现的,很显然有很多并不是最优的解法,甚至有的时间复杂度过高,大家有什么意见建议欢迎留言提出,希望能对你有所帮助。
所有分析和代码在这里这里这里

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值