算法学习--线性表

链表反转:

链表反转也是比较常见的一个面试题。

方法1. 迭代。 分别设置三个指针。第一个指针保持结果,第二个指针指向当前的节点,第三个指针保存下一个节点。

static void reverse(struct node** head_ref)
{
    struct node* prev   = NULL;
    struct node* current = *head_ref;
    struct node* next;
    while (current != NULL)
    {
        next  = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }
    *head_ref = prev;
}

方法2:使用递归

	/* 使用递归的方法 */
static struct node * reverseRecall(struct node* head){
    //最后一个节点会返回 作为头部
    if(NULL == head || head->next == NULL) return head;
    //head->next 表示剩下的部分
    struct node * newHead = reverseRecall(head->next);
    head->next->next = head; //颠倒指针
    head->next = NULL;//原来的头节点 next 应该为空
    return newHead;
}

链表排序:

对链表进行排序,要求的时间复杂度为O(n log n)。nlogn的排序有快速排序、归并排序、堆排序。双向链表用快排比较适合,堆排序也可以用于链表,单向链表适合用归并排序。题目要求的是常数的空间复杂度,因为这里用了递归,如果算上栈空间的话,也要 o(logn)的复杂度。

关于链表的划分,这里使用了快慢指针,从中间节点进行切开成单独的链表。在merge之后又会合并成一个链表

    public static  ListNode sortList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode slow = head;
        ListNode fast = head;
        //用快慢指针找到中间节点
        while(fast.next != null && fast.next.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode list2 = slow.next;
        slow.next = null;
        head = sortList(head);
        list2 = sortList(list2);
        return merge(head, list2);
    }
 
    private static ListNode merge(ListNode list1, ListNode list2) {
        if(list1 == null) return list2;
        if(list2 == null) return list1;
        ListNode newHead = new ListNode(0);//链表头不存储实际数据
        ListNode last = newHead;
        last = newHead;
        //连接每个节点,只更换指针,因此空间复杂度为O(1)
        while(list1 != null && list2 != null){
            if(list1.val < list2.val){
                last.next = list1;
                list1 = list1.next;
            }else{
                last.next = list2;
                list2 = list2.next;
            }
            last = last.next;
        }
        //最后剩余的部分,直接连接起来即可
        if(list1 != null) last.next = list1;
        else if(list2 != null) last.next = list2;
        return newHead.next;
    }

链表中倒数第K个节点:

第一个指针先走k-1步,然后第二个指针在head,两个指针同时走,当第一个指针走到最后时,第二个指针指向的就是倒数第K个节点。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值