力扣 61. 旋转链表 暴力破解

简介: 力扣 61. 旋转链表 暴力破解

题目


image.png

image.png



想法


题目如上图所示

根据题目,输入一个数字k ,使 链表 向右旋转 k 次,将得到一个新链表,然后将此链表返回。

复述一下旋转的过程

原有链表

image.png

旋转次数: 2

第一次旋转

image.png

第二次旋转

image.png

此链表就是我们的新链表



解决方法


: 如果我们能够将最后一个节点拿到前面来,重复k次,不就能够解决该题目了么?


我们补充下Head 和 NULL 节点,再次来模拟一下旋转过程


该题目没有Head节点,Head节点指的是第一个节点


原始链表

image.png

旋转一次链表

image.png


注意到: 我们应该有3步操作

  1. 获取最后一个链表
  2. 将最后一个链表的下一个指针指向第一个链表
  3. 将倒数第二个链表的下一个指针指向NULL

以上方法重复k次,就可以解决该问题




伪代码


旋转伪代码

for (i=0;i<k;i++) 
    last,end = getListLasts(head) //last: 获取倒数第二个链表数据 end: 获取倒数第一个链表数
    end->next = head // 将倒数第一个链表数据的下一个节点指向 头节点
    last->next = NULL // 将倒数第二个链表数据的下一个节点指向 NULL
    head = end // 将头结点指向旋转后的节点


获取最后的节点伪代码

curr = head
while curr->next != NULL {
    last = curr // 记录倒数第二个
    curr遍历下一个
}



解题


根据伪代码,我们顺利写出实际代码

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func rotateRight(head *ListNode, k int) *ListNode {
    if nil == head || nil == head.Next  {
        return head
    }
    for i:=0;i<k;i++ {
        last , end := getListEnds(head)
        last.Next = nil
        end.Next = head
        head = end
    }
    return head
}
func getListEnds(head *ListNode) (*ListNode,*ListNode) {
    var curr *ListNode
    var last *ListNode
    curr = head
    for curr.Next != nil {
        last = curr
        curr = curr.Next
    }
    return last,curr
}




提交之后,超出时间限制。。。。


image.png



重新思考循环


如报错所示,循环 200000... 次的确很恐怖,

不过发现如下规则

循环的次数的效果 == k % (链表长度)

即: 循环 2000000000 次,等同于 2000000000 % 3 (链表长度) == 2 次,实际选择2次即可


重新提交代码

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func rotateRight(head *ListNode, k int) *ListNode {
    // fmt.Println(listLen(head))
    if nil == head || nil == head.Next  {
        return head
    }
    for i:=0;i<(k%listLen(head));i++ {
        last , end := getListEnds(head)
        last.Next = nil
        end.Next = head
        head = end
    }
    return head
}
// 获取链表长度
func listLen(head *ListNode) int {
    i := 0
    var curr *ListNode
    curr = head
    for curr != nil {
        i++
        curr = curr.Next
    }
    return i
}
// 获取最后一个节点 和 倒数第二个节点
func getListEnds(head *ListNode) (*ListNode,*ListNode) {
    var curr *ListNode
    var last *ListNode
    curr = head
    for curr.Next != nil {
        last = curr
        curr = curr.Next
    }
    return last,curr
}




思考


该题目考验的是对链表的熟悉程度,只要熟悉链表,一般就能解决问题,解决的方法不止一个,我通常的做法是,先使用暴力破解,尝试是否能够正常解决此问题,然后再对暴力破解进行分析,顺带看看能不能优化该算法。

相关文章
|
1月前
|
算法
LeetCode刷题---21.合并两个有序链表(双指针)
LeetCode刷题---21.合并两个有序链表(双指针)
|
1月前
|
算法
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
【移除链表元素】LeetCode第203题讲解
【移除链表元素】LeetCode第203题讲解
|
1月前
|
算法 测试技术
LeetCode刷题--- 430. 扁平化多级双向链表(深度优先搜索)
LeetCode刷题--- 430. 扁平化多级双向链表(深度优先搜索)
|
1月前
|
存储
实现单链表的基本操作(力扣、牛客刷题的基础&笔试题常客)
实现单链表的基本操作(力扣、牛客刷题的基础&笔试题常客)
143 38
|
11天前
【力扣】21. 合并两个有序链表
【力扣】21. 合并两个有序链表
|
1月前
|
存储 JavaScript
leetcode82. 删除排序链表中的重复元素 II
leetcode82. 删除排序链表中的重复元素 II
22 0
|
1月前
leetcode83. 删除排序链表中的重复元素
leetcode83. 删除排序链表中的重复元素
10 0
|
1月前
leetcode2807.在链表中插入最大公约数
leetcode2807.在链表中插入最大公约数
16 0
|
1月前
leetcode2487.从链表中移除节点
leetcode2487.从链表中移除节点
20 1