力扣 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
}




思考


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

相关文章
|
2月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
37 1
|
2月前
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
51 0
Leetcode第21题(合并两个有序链表)
|
2月前
|
算法
【链表】算法题(二) ----- 力扣/牛客
【链表】算法题(二) ----- 力扣/牛客
|
2月前
|
机器学习/深度学习
Leetcode第48题(旋转图像)
这篇文章介绍了LeetCode第48题“旋转图像”的解题方法,通过原地修改二维矩阵实现图像的顺时针旋转90度。
32 0
Leetcode第48题(旋转图像)
|
2月前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
23 0
Leetcode第三十三题(搜索旋转排序数组)
|
2月前
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
22 0
LeetCode第二十四题(两两交换链表中的节点)
|
2月前
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
44 0
Leetcode第十九题(删除链表的倒数第N个节点)
|
2月前
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
90 0
|
2月前
【LeetCode 10】142. 环形链表 II
【LeetCode 10】142. 环形链表 II
22 0
|
2月前
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
17 0