60、排列序列,61、旋转链表——LeetCode

60、排列序列

题目

给出集合 [1,2,3,...,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

  1. "123"

  2. "132"

  3. "213"

  4. "231"

  5. "312"

  6. "321"

给定 n 和 k,返回第 k 个排列。

示例 1:

输入:n = 3, k = 3
输出:"213"

Code

class Solution {
    public String getPermutation(int n, int k) {
        int[] factorial = new int[n];
        factorial[0] = 1;
        for (int i = 1; i < n; ++i) {
            factorial[i] = factorial[i - 1] * i;
        }

        --k;
        StringBuffer ans = new StringBuffer();
        int[] valid = new int[n + 1];
        Arrays.fill(valid, 1);
        for (int i = 1; i <= n; ++i) {
            int order = k / factorial[n - i] + 1;
            for (int j = 1; j <= n; ++j) {
                order -= valid[j];
                if (order == 0) {
                    ans.append(j);
                    valid[j] = 0;
                    break;
                }
            }
            k %= factorial[n - i];
        }
        return ans.toString();
    }
}

61、旋转链表

题目

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

示例:

输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]

解题思路

  1. 理解问题:题目要求将链表向右旋转k个位置。例如,对于链表[1, 2, 3, 4, 5],k=2,旋转后应得到[4, 5, 1, 2, 3]。

  2. 特殊情况处理:如果链表为空、只有一个节点或k为0,则无需旋转,直接返回原始头节点。

  3. 计算链表长度:遍历链表以确定其长度。

  4. 调整k值:如果k大于链表长度,使用k % 长度来找到实际需要旋转的节点数。

  5. 找到旋转断开点:遍历链表,找到第(长度 - k)个节点,该节点的下一个节点将是旋转后链表的新头节点。

  6. 执行旋转:将找到的节点的next设置为null,切断链表。然后将链表的末尾节点连接到原始头节点,形成旋转后的链表。

解题过程

  1. 初始化:创建一个指针current用于遍历链表,两个指针newHeadtail分别用于存储新头节点和末尾节点。

  2. 计算长度:使用current遍历链表,计算并存储链表长度。

  3. 特殊情况:如果链表长度小于等于1或k为0,直接返回原始头节点。

  4. 调整k:如果k大于链表长度,更新k为k % 长度。

  5. 找到新头节点:使用两个指针slowfastfast移动速度是slow的k倍,当fast到达链表末尾时,slow所在位置的下一个节点即为新头节点。

  6. 断开并连接链表:将slownext设置为null,切断链表。然后将current(末尾节点)的next指向原始头节点,完成旋转。

复杂度

  • 时间复杂度:O(n),其中n是链表的长度。需要遍历整个链表来确定长度和找到旋转点。

  • 空间复杂度:O(1),只需要几个额外的指针变量,不依赖于输入大小。

Code

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || head.next == null || k == 0) {
            return head;
        }

        int length = 1;
        ListNode current = head;
        while (current.next != null) {
            current = current.next;
            length++;
        }

        k = k % length;
        if (k == 0) {
            return head;
        }

        current = head;
        for (int i = 1; i < length - k; i++) {
            current = current.next;
        }

        ListNode newHead = current.next;
        current.next = null;
        ListNode tail = newHead;
        while (tail.next != null) {
            tail = tail.next;
        }
        tail.next = head;
        
        return newHead;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值