旋转链表

题目:

给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入: 1->2->3->4->5->NULL, k = 2

输出: 4->5->1->2->3->NULL

解释:

向右旋转 1 步: 5->1->2->3->4->NULL

向右旋转 2 步: 4->5->1->2->3->NULL

示例 2:

输入: 0->1->2->NULL, k = 4

输出: 2->0->1->NULL

解释:

向右旋转 1 步: 2->0->1->NULL

向右旋转 2 步: 1->2->0->NULL

向右旋转 3 步: 0->1->2->NULL

向右旋转 4 步: 2->0->1->NULL

思路:

再说这个题目的解题步骤之前先说说这个题目的理解,就是链表倒着数k个结点,然后断开k+1和k个结点之间的联接将其分成两个链表。然后将前后两个链表调换一下位置重新连接起来。(当然当k大于链表长度的时候需要取模运算)

1.计算链表的长度。

2.定义一个指针pPre指向头结点,移动k步。

3.定义一个指针pCur指向头结点,同时向前移动pPre和pCur指针直到pPre遍历完整个链表,此时pCur即为倒数第k个结点。

4.在第k个结点处断开链表,再将前后两个链表交换顺序后重新连接起来。

代码:

ListNode* rotateRight(ListNode* head, int k) {
if (head == NULL || head->next == NULL)
{
return head;
}
ListNode* pPre = head;
int count = 0;
while (pPre != NULL)
{
pPre = pPre->next;
count++;
}
ListNode* pCur = head;
pPre = head;
for (int i = 0; i < k % count; i++)
{
pPre = pPre->next;
}
if (pPre != NULL)
{
while (pPre->next != NULL)
{
pPre = pPre->next;
pCur = pCur->next;
}
pPre->next = head;
head = pCur->next;
pCur->next = NULL;
}
return head;
}

改进版:

ListNode* rotateRight(ListNode* head, int k) {
if (head == NULL || k == 0)
{
return head;
}
int count = 1;
ListNode* p = head;
while (p->next)
{
count++;
p = p->next;
}
int left = count - k % count;
p->next = head;
for (int i = 0; i < left; ++i)
{
p = p->next;
}
head = p->next;
p->next = NULL;
return head;
}

总结:

1.解题的关键是如何将题目转化为找到倒数第k个结点

2.另外一个巧妙的地方是循环向前移动两个指针的时候判断的是pPre->next是否为NULL,这样可以将pPre和pCur分别定位到断开链表后的的最后一个结点上,方便断开的链表进行联接。

3.改进版是我在网上看到别人的思路实现的。首先统计整个链表的长度,同时将一个指针指向链表的最后一个结点,然后将链表首尾联接起来,组成一个环,然后用数学的方法计算出正着数应该移动left步,然后将指向最后一个结点的指针移动left步,最后在这个位置将链表断开即得到结果。

有时候思路真的就是一层窗户纸

leetcode腾讯精选练习之旋转链表(四)的更多相关文章

  1. leetcode腾讯精选练习之相交链表(六)

    相交链表 题目: 编写一个程序,找到两个单链表相交的起始节点. 如下面的两个链表: 在节点 c1 开始相交. 示例 1: 输入:intersectVal = 8, listA = [4,1,8,4,5 ...

  2. LeetCode 腾讯精选50题--链表排序

    解题思路:归并 先把链表拆开,分为两部分,一直拆到只剩一个元素后,进行合并,利用一个临时节点记录重排后的链表的起始位置 合并不难,困难点在于如何拆分链表,自己的大体思路是利用两个指针,一个一次移动两位 ...

  3. LeetCode 腾讯精选50题--合并K个排序链表

    今天的题目稍微有点复杂了,因为是K个有序链表的合并,看到这道题后的大体思路是这样的: 1.首先先做到两个链表的合并,链表的合并我想到的是用递归操作, 2.其次是多个链表的合并,所以在第一步实现的基础上 ...

  4. LeetCode OJ:Rotate List(旋转链表)

    Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given 1 ...

  5. leetcode腾讯精选练习之两数相加

    两数相加 题目: 给出两个非空的链表用来表示两个非负的整数.其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字.如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们 ...

  6. leetcode腾讯精选练习(50 题)(持续更新)

    1.除自身以外数组的乘积 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘 ...

  7. LeetCode 腾讯精选50题--二叉树中的最大路径和

    二叉树中的最大路径和 题目描述 给定一个非空二叉树,返回器最大路径和,路径指一条从任意节点出发,到达任意节点的序列,该路径至少包含一个节点,且不一定经过根节点 解题思路 树这一类数据结构我还不是很熟悉 ...

  8. LeetCode 腾讯精选50题--二叉树的最大深度

    求二叉树的最大深度, 基本思路如下: 设定一个全局变量记录二叉树的深度,利用递归,没遍历一层都将临时深度变量+1,并在每一节点递归结束后判断深度大小. 具体代码如下: package algorith ...

  9. LeetCode 腾讯精选50题--2的幂

    在二进制中,2的幂的数字用二进制表示时只会有一位表示为1,其余都为0,基于这个前提,可以有两种方案: 1. 做位移操作 2. 与数值取反并与原数值做与操作,判断是否与原来的数值相同 对于方案1,我的想 ...

随机推荐

  1. spring4.2.4整合ehcache

    最近工作中遇到个功能需要整合ehcache,由于spring版本用的是4.2.4,而在ehcache官网找到的集成配置文档是spring3.1的,因此配了几次都不成功,在历经一番波折后终于成功集成了s ...

  2. vue的v-if和v-show的区别

    引言 vue这两条指令,在面试vue经常会被问道它们的区别,今天我也好好查看了以下文档,做做笔记. 相同点 它们都用于条件渲染,都可以隐藏和显示DOM元素. v-if 通过判断条件成立与否,适当的销毁 ...

  3. hashmap 的边遍历边存储

    PS: Hashmap 的一边遍历边存储,可解决例如两数之和. 无重复最长子串问题等,代码为cpp格式. 以无重复最长子串为例. class Solution { public: int length ...

  4. ROS和Gazebo进行机器人仿真(二)

    一.在Gazebo中使用ROS控制器 在本节中,我们将讨论如何在Gazebo中让机器人的每个关节运动. 为了让关节动起来,我们需要分配一个ROS控制器,尤其是,我们需要为每个关节连上一个与transm ...

  5. C语言实现银行家算法

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h& ...

  6. HDU_2510_打表

    http://acm.hdu.edu.cn/showproblem.php?pid=2510 dfs打表. #include<iostream> #include<cstdio> ...

  7. angular 控件间的通信

    先引入 设置meta元素 http://blog.sina.com.cn/s/blog_51048da70101cgea.html //设置 虚拟窗口的大小等于设备的大小 <meta name= ...

  8. 不用'+'完成a + b

    这也是'+'底层运算原理: #include<bits/stdc++.h> using namespace std; int a,b; int main() { scanf("% ...

  9. 阿里云服务器ECS Ubuntu18.04 安装mysql

    ubuntu系统好了,这下我应该安装MySQL数据库了.在安装过程中,遇到好多坑,下面是我的安装过程. 1.在阿里云控制台,用vnc登录到服务器. 用新的用户登录到Ubuntu用户系统. 打开终端: ...

  10. [Effective Java 读书笔记] 第6章 枚举和注解

    第三十条 用enum代替int 总得来说,使用enum有几点好处 1.编译时的类型安全, 2.可以保证就是自己定义的值,不会有月结风险, 3.每个枚举类型有自己的命名空间 4.枚举可以添加任意的方法和 ...