【Leetcode】1238. Circular Permutation in Binary Representation

题目地址:

https://leetcode.com/problems/circular-permutation-in-binary-representation/

给定两个正整数 n n n s s s,要求返回一个长 2 n 2^n 2n的列表,使得其以 s s s开头,并且任意相邻两个数字的二进制表示恰好有一位不同,且首尾的两个数字也如此。

其实就是格雷码问题,可以递归地解决。若 n = 1 n=1 n=1,则 ( 0 , 1 ) (0,1) (0,1)即为满足条件的格雷码。若 n ≥ 2 n\ge 2 n2,假设已经生成了 n − 1 n-1 n1的格雷码,现在将这个格雷码每个数字加上 2 n − 1 2^{n-1} 2n1后,再逆序然后接在原列表后面,就得到了长 2 n 2^n 2n的列表,该列表就是合法的格雷码。当然实际写程序的时候可以写成循环的形式。代码如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {
    public List<Integer> circularPermutation(int n, int start) {
        List<Integer> list = new ArrayList<>(Arrays.asList(0, 1));
        for (int i = 0; i < n - 1; i++) {
            int size = list.size();
            for (int j = 0; j < size; j++) {
                list.add(list.get(size - 1 - j) + (1 << i + 1));
            }
        }
        
        // 找到start的位置
        int idx = 0;
        while (list.get(idx) != start) {
            idx++;
        }
        
        // 变为以start开始
        List<Integer> res = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            res.add(list.get(idx + i < list.size() ? idx + i : idx + i - list.size()));
        }
        
        return res;
    }
}

时空复杂度 O ( 2 n ) O(2^n) O(2n)

也可以不递归地做。考虑 f ( k ) = k ∧ ( k > > 1 ) f(k)=k\wedge (k>>1) f(k)=k(k>>1),当 k k k 0 0 0取到 2 n − 1 2^n-1 2n1的时候, f f f就取遍了格雷码。而 f ( 0 ) = 0 f(0)=0 f(0)=0,所以 s ∧ f ( k ) s\wedge f(k) sf(k)也取遍了格雷码,并且以 s s s开头。代码如下:

import java.util.ArrayList;
import java.util.List;

public class Solution {
    public List<Integer> circularPermutation(int n, int start) {
        List<Integer> res = new ArrayList<>();
        for (int i = 0; i < 1 << n; i++) {
            res.add(start ^ i ^ i >> 1);
        }
        
        return res;
    }
}

时间复杂度 O ( 2 n ) O(2^n) O(2n),空间 O ( 1 ) O(1) O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值