本文已参与「新人创作礼」活动,一起开启掘金创作之路。
6000. 对奇偶下标分别排序
给你一个下标从 0 开始的整数数组 nums 。根据下述规则重排 nums 中的值:
按 非递增 顺序排列 nums 奇数下标 上的所有值。 举个例子,如果排序前 nums = [4,1,2,3] ,对奇数下标的值排序后变为 [4,3,2,1] 。奇数下标 1 和 3 的值按照非递增顺序重排。 按 非递减 顺序排列 nums 偶数下标 上的所有值。 举个例子,如果排序前 nums = [4,1,2,3] ,对偶数下标的值排序后变为 [2,1,4,3] 。偶数下标 0 和 2 的值按照非递减顺序重排。 返回重排 nums 的值之后形成的数组。
示例 1:
输入:nums = [4,1,2,3] 输出:[2,3,4,1] 解释: 首先,按非递增顺序重排奇数下标(1 和 3)的值。 所以,nums 从 [4,1,2,3] 变为 [4,3,2,1] 。 然后,按非递减顺序重排偶数下标(0 和 2)的值。 所以,nums 从 [4,1,2,3] 变为 [2,3,4,1] 。 因此,重排之后形成的数组是 [2,3,4,1] 。
示例 2:
输入:nums = [2,1] 输出:[2,1] 解释: 由于只有一个奇数下标和一个偶数下标,所以不会发生重排。 形成的结果数组是 [2,1] ,和初始数组一样。
提示:
1 <= nums.length <= 100 1 <= nums[i] <= 100
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/so…
分析
分部分排序即可
C++代码
class Solution {
public:
vector<int> sortEvenOdd(vector<int>& nums) {
for(int i=0; i < nums.size(); i+=2){
for(int j=i+2; j < nums.size(); j+= 2){
if(nums[i] > nums[j]){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
}
for(int i=1; i < nums.size(); i+=2){
for(int j=i+2; j < nums.size(); j+= 2){
if(nums[i] < nums[j]){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
}
return nums;
}
};
python代码
class Solution:
def sortEvenOdd(self, nums: List[int]) -> List[int]:
nums[::2] = sorted(nums[::2])
nums[1::2] = sorted(nums[1::2], reverse=True)
return nums
6001. 重排数字的最小值
给你一个整数 num 。重排 num 中的各位数字,使其值 最小化 且不含 任何 前导零。
返回不含前导零且值最小的重排数字。
注意,重排各位数字后,num 的符号不会改变。
示例 1:
输入:num = 310 输出:103 解释:310 中各位数字的可行排列有:013、031、103、130、301、310 。 不含任何前导零且值最小的重排数字是 103 。
示例 2:
输入:num = -7605 输出:-7650 解释:-7605 中各位数字的部分可行排列为:-7650、-6705、-5076、-0567。 不含任何前导零且值最小的重排数字是 -7650 。
提示:
-1015 <= num <= 1015
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/sm…
C++代码
class Solution {
public:
long long smallestNumber(long long num) {
bool flag=true;
if(num < 0){
flag = false;
num = -num;
}
vector<int> v;
while(num){
v.push_back(num % 10);
num /= 10;
}
sort(v.begin(), v.end());
long long ans = 0;
if(flag){
if(v.size() == 0){
return 0;
}
if(v[0] == 0){
int cnt=0;
int cur=0;
while(v[cur] == 0){
cnt++;
cur++;
}
ans = v[cur];
while(cnt--){
ans *= 10;
}
for(int i=cur+1; i < v.size(); i++){
ans *= 10;
ans += v[i];
}
}else{
for(int i=0; i < v.size(); i++){
ans *= 10;
ans += v[i];
}
}
return ans;
}else{
for(int i=v.size()-1; i >= 0 ; i--){
ans *= 10;
ans += v[i];
}
return -ans;
}
}
};
python代码
class Solution:
def smallestNumber(self, num: int) -> int:
flag = num > 0
if flag == False:
num = -num
ls = []
while num:
ls.append(num % 10)
num //= 10
ls = sorted(ls);
ans=0
if flag:
cur = 0
while ls[cur] == 0:
cur+=1
ans = ls[cur]
for i in range(cur):
ans *= 10
for i in range(cur+1, len(ls)):
ans *= 10
ans += ls[i]
return ans
else:
for i in range(len(ls)-1, -1, -1):
ans *= 10
ans += ls[i]
return -ans
6002. 设计位集
位集 Bitset 是一种能以紧凑形式存储位的数据结构。
请你实现 Bitset 类。
Bitset(int size) 用 size 个位初始化 Bitset ,所有位都是 0 。 void fix(int idx) 将下标为 idx 的位上的值更新为 1 。如果值已经是 1 ,则不会发生任何改变。 void unfix(int idx) 将下标为 idx 的位上的值更新为 0 。如果值已经是 0 ,则不会发生任何改变。 void flip() 翻转 Bitset 中每一位上的值。换句话说,所有值为 0 的位将会变成 1 ,反之亦然。 boolean all() 检查 Bitset 中 每一位 的值是否都是 1 。如果满足此条件,返回 true ;否则,返回 false 。 boolean one() 检查 Bitset 中 是否 至少一位 的值是 1 。如果满足此条件,返回 true ;否则,返回 false 。 int count() 返回 Bitset 中值为 1 的位的 总数 。 String toString() 返回 Bitset 的当前组成情况。注意,在结果字符串中,第 i 个下标处的字符应该与 Bitset 中的第 i 位一致。
示例:
输入 ["Bitset", "fix", "fix", "flip", "all", "unfix", "flip", "one", "unfix", "count", "toString"] [[5], [3], [1], [], [], [0], [], [], [0], [], []] 输出 [null, null, null, null, false, null, null, true, null, 2, "01010"]
解释 Bitset bs = new Bitset(5); // bitset = "00000". bs.fix(3); // 将 idx = 3 处的值更新为 1 ,此时 bitset = "00010" 。 bs.fix(1); // 将 idx = 1 处的值更新为 1 ,此时 bitset = "01010" 。 bs.flip(); // 翻转每一位上的值,此时 bitset = "10101" 。 bs.all(); // 返回 False ,bitset 中的值不全为 1 。 bs.unfix(0);
// 将 idx = 0 处的值更新为 0 ,此时 bitset = "00101" 。 bs.flip(); // 翻转每一位上的值,此时 bitset = "11010" 。 bs.one(); // 返回 True ,至少存在一位的值为 1 。 bs.unfix(0); // 将 idx = 0 处的值更新为 0 ,此时 bitset = "01010" 。 bs.count(); // 返回 2 ,当前有 2 位的值为 1 。 bs.toString(); // 返回 "01010" ,即 bitset 的当前组成情况。
提示:
1 <= size <= 105 0 <= idx <= size - 1 至多调用 fix、unfix、flip、all、one、count 和 toString 方法 总共 105 次 至少调用 all、one、count 或 toString 方法一次 至多调用 toString 方法 5 次
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/de…
分析
从题意看出应该是二进制的题目,但是因为size过大,所以C++中用字符串表示二进制数,同时因为反转步骤和统计步骤容易超时,我们同步存储反转的结果和1的个数。
C++代码
class Bitset {
public:
string n;
string ren;
int ones=0;
int csize;
Bitset(int size) {
csize = size;
for(int i=0; i < size; i++){
n += "0";
ren += "1";
}
}
void fix(int idx) {
if(n[idx] == '0'){
n[idx] = '1';
ren[idx] = '0';
ones++;
}
}
void unfix(int idx) {
if(n[idx] == '1'){
n[idx] = '0';
ren[idx] = '1';
ones--;
}
}
void flip() {
string tmp = n;
n = ren;
ren = tmp;
ones = csize - ones;
}
bool all() {
return ones == csize;
}
bool one() {
return ones > 0;
}
int count() {
return ones;
}
string toString() {
return n;
}
};
/**
* Your Bitset object will be instantiated and called as such:
* Bitset* obj = new Bitset(size);
* obj->fix(idx);
* obj->unfix(idx);
* obj->flip();
* bool param_4 = obj->all();
* bool param_5 = obj->one();
* int param_6 = obj->count();
* string param_7 = obj->toString();
*/
python代码
class Bitset:
def __init__(self, size: int):
self.num = 0
self.len = size
self.total = 0
self.power = 1 << self.len
def fix(self, idx: int) -> None:
idx = self.len - idx - 1
if not (self.num >> idx) & 1:
self.total += 1
self.num |= (1 << idx)
def unfix(self, idx: int) -> None:
idx = self.len - idx - 1
if (self.num >> idx) & 1:
self.total -= 1
self.num ^= (1 << idx)
def flip(self) -> None:
self.total = self.len - self.total
self.num = self.power - 1 - self.num
def all(self) -> bool:
return self.total == self.len
def one(self) -> bool:
return self.total > 0
def count(self) -> int:
return self.total
def toString(self) -> str:
s = bin(self.num)[2:]
return "0" * (self.len - len(s)) + s
# Your Bitset object will be instantiated and called as such:
# obj = Bitset(size)
# obj.fix(idx)
# obj.unfix(idx)
# obj.flip()
# param_4 = obj.all()
# param_5 = obj.one()
# param_6 = obj.count()
# param_7 = obj.toString()
6003. 移除所有载有违禁货物车厢所需的最少时间
给你一个下标从 0 开始的二进制字符串 s ,表示一个列车车厢序列。s[i] = '0' 表示第 i 节车厢 不 含违禁货物,而 s[i] = '1' 表示第 i 节车厢含违禁货物。
作为列车长,你需要清理掉所有载有违禁货物的车厢。你可以不限次数执行下述三种操作中的任意一个:
从列车 左 端移除一节车厢(即移除 s[0]),用去 1 单位时间。 从列车 右 端移除一节车厢(即移除 s[s.length - 1]),用去 1 单位时间。 从列车车厢序列的 任意位置 移除一节车厢,用去 2 单位时间。 返回移除所有载有违禁货物车厢所需要的 最少 单位时间数。
注意,空的列车车厢序列视为没有车厢含违禁货物。
示例 1:
输入:s = "1100101" 输出:5 解释: 一种从序列中移除所有载有违禁货物的车厢的方法是:
- 从左端移除一节车厢 2 次。所用时间是 2 * 1 = 2 。
- 从右端移除一节车厢 1 次。所用时间是 1 。
- 移除序列中间位置载有违禁货物的车厢。所用时间是 2 。 总时间是 2 + 1 + 2 = 5 。
一种替代方法是:
- 从左端移除一节车厢 2 次。所用时间是 2 * 1 = 2 。
- 从右端移除一节车厢 3 次。所用时间是 3 * 1 = 3 。 总时间也是 2 + 3 = 5 。
5 是移除所有载有违禁货物的车厢所需要的最少单位时间数。 没有其他方法能够用更少的时间移除这些车厢。
示例 2:
输入:s = "0010" 输出:2 解释: 一种从序列中移除所有载有违禁货物的车厢的方法是:
- 从左端移除一节车厢 3 次。所用时间是 3 * 1 = 3 。 总时间是 3.
另一种从序列中移除所有载有违禁货物的车厢的方法是:
- 移除序列中间位置载有违禁货物的车厢。所用时间是 2 。 总时间是 2.
另一种从序列中移除所有载有违禁货物的车厢的方法是:
- 从右端移除一节车厢 2 次。所用时间是 2 * 1 = 2 。 总时间是 2.
2 是移除所有载有违禁货物的车厢所需要的最少单位时间数。 没有其他方法能够用更少的时间移除这些车厢。
提示:
1 <= s.length <= 2 * 105 s[i] 为 '0' 或 '1'
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/mi…
分析
动态规划的题目,不妨假设i为当前位置dp[i]为从右删(包括到中间删除)到i的最小值,然后遍历查询从左侧删到i即可
C++代码
class Solution {
public:
int minimumTime(string s) {
int n = s.size();
int dp[n+1];
memset(dp, 0, sizeof(dp));
for(int i=n-1; i >= 0; i--){
if(s[i] == '0'){
dp[i] = dp[i+1];
}else{
dp[i] = min(dp[i+1]+2, n - i);
}
}
int cur = 0;
int ans = dp[0];
for(int i=0; i < n; i++){
if(s[i] == '1'){
cur = min(cur+2, i+1);
ans = min(ans, cur + dp[i+1]);
}
}
return ans;
}
};