数据结构_单链表小题-2.2

一. 合并两个升序单链表

把两个单链表,按升序排列为一个单链表。

看到就想到的思路

1)看首链表谁小,作为一个首地址存了,假设为l1;
2)遍历另一个链表l2,比较其是否在l1的第一和第二结点值区间里;
3)在,就插入;不在,比较l1的第二个和第三个结点值区间,依次类推;
4)l1或l2遍历完了,就连起来。返回第一步存的首地址。
例如:[1->3]->5->7 和2->2->3->4->6

问题

1)写起来的时候,感觉很麻烦
2)你知道了链表l2在l1的第一和第二区间里,这相当于内部插入,内部插入,你l2的结点要指向l1的第二个结点,l1第一个指向l2结点,l2结点的下一个next也要被保存下来。很麻烦。

参考思路:尾插

1)看首链表谁小,作为一个首地址存了,假设为l1;
2)比较l1的第二个结点和l2的第一个结点,谁小,尾插在1)的首结点后。
3)看l1和l2谁先走完,最后连起来。

增益点

1.能头插,尾插,就不要想中间插入

现在回看,我没必要把l2的结点和l1的第二个结点连起来,多此一举。但为什么我会最先想到这种思路呢?我是先以一个链表为参考,把另一个链表打碎放入这个参考链表里。这反而禁锢了。

2.尾插,哨兵结点

无头结点:开始为NULL的结点
哨兵结点:自己开辟的一块不存储有效数据的结点
哨兵结点更容易尾插,更容易找到首链表的地址,也就是起始地址,这方便的多。
无头结点,你需要比较l1和l2的首结点谁小,再作为起始地址,麻烦些。

代码:无头结点

无头结点还需要把头存起来啊,麻烦了

mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    Node* n1 = list1;
    Node* n2 = list2;

    Node* store = NULL;
    Node* n3 = NULL;

    if (n1->val >= n2->val)
    {
        store = n2;
        n2 = n2->next;

    }
    else
    {
        store = n1;
        n1 = n1->next;

    }
    n3 = store; 这里无头结点还需要把头存起来啊,麻烦了
    while (n1 && n2)
    {
        if (n1->val > n2->val)
        {
            n3->next = n2;
            n2 = n2->next;

        }
        else
        {
            n3->next = n1;
            n1 = n1->next;

        }
        n3 = n3->next;

    }
    if (n1 == NULL)
        n3->next = n2;
    else
        n3->next = n1;
    return store;
}

二. 以某个值为界限,重排链表

小于x放链表前面,大于等于的放后面。

刚看到的思路

1)哨兵结点,找大的,尾插
2)哨兵结点,找小的,尾插
3)小连大

和参考思路一致,但是一直有一个超时的错误

增益点:防止环,next指向常设NULL

这里的尾插在最后
1)small的next是指向big链表的
2)但是big的最后结点是指向small的最后一部分结点的,相当于成一个环路了。
3)small指向big,big又指向small最后一部分结点,相当于big一直在循环

代码

超时错误的原因是,少了big->next=NULL;,导致链表成环,无限循环

typedef struct ListNode Node;
struct ListNode* partition(struct ListNode* head, int x) {
    
    Node* small=(Node*)malloc(sizeof(Node));
    Node* smallstore=small;

    Node* big=(Node*)malloc(sizeof(Node));
    Node* bigstore=big;
    Node* cur=head;
    if (head == NULL)
        return head;
    while(cur)
    {
        if(cur->val<x)
        {
            small->next=cur;
            cur=cur->next;
            small=small->next;
        }
        else
        {
            big->next=cur;
            cur=cur->next;
            big=big->next;
        }
    }
    big->next=NULL;-----------------超时原因
    small->next=bigstore->next;


    return smallstore->next;

}

三. 数组有两个元素出现一次,其余都出现两次

找出现一次的这两个元素。难嘞,加减不行,异或不行。

参考思路

1)异或,得到两个元素的异或值
(难不成你还能分离出这两个元素不成?)
2)异或的特点,某个位是1,则x1的这个位和x2的这个位不同,分别为0和1
3)找出第M位为1的组,和M位为0的组。
4)两组各自做异或,找出单独的两个元素。这样就成数组有一个元素出现一次,其余出现两次了。

用处不大的增益点:位

对位的操作可能会使解题更加便捷。谁想到到?这里的看第M位是否为1,再进行分组。

你可能感兴趣的:(数据结构,学习,c语言,开发语言)