1545 找出第N个二进制字符串的第K位 #分治

题目链接

题意

给定正整数\(n(\leq 20)\)与\(k\),二进制串\(S_n\)形成规则有:

  • \(S_1 = “0”\)

  • 当\(i>1\)时,\(S_i = S_{i-1}+“1”+reverse(invert(S_{i-1}))\)

    其中\(reverse(x)\)表示左右反转字符串x,\(invert(x)\)表示翻转x中的每一位(0->1,1->0)

现要返回\(S_n\)的第\(k\)位字符

如:\(n=3,k=1\),可以得到\(S_3=“0111001”\),其第一位为"0",故返回"0"

分析

本来想打表,但最后的串实在是长。我们不必从n=1一步步模拟整个过程,而是自顶而下深入递归,只关心第\(k\)位属于上一步形成的01串的哪个位置哪个字符。

我们容易推出,对于\(S_n\)形成的串为\(2^n-1\)长度的01串,我们比较\(k\)与\(2^{n-1}\)的大小:

  • 如果\(k=2^{n-1}\),它在串最中间,字符为"1",直接返回即可
  • 如果\(k<2^{n-1}\),它在当前串的左部分,由串的形成规则可知,串左部分是经上一轮的串直接复制得到的,那么递归\(n-1\)次操作的第\(k\)位即可
  • 如果\(k>2^{n-1}\),由串的形成规则,串右部分是经过上一轮串的反转+翻转得到的,那么当前的第k位是由上一轮的\(2^n-1-k+1\)位置得到的,当然别忘了对返回结果的字符进行取反操作!
class Solution {
public:
char Trans(char now) {
return (now == '1') ? '0' : '1';
}
char findKthBit(int n, int k) {
if (n == 1) return '0';
int len = 1 << (n - 1);
if (k == len) return '1';
else if (k < len) return findKthBit(n - 1, k);
else {
return Trans(findKthBit(n - 1, (len << 1) - k));
}
}
};

1546 和为目标值的最大数目不重叠非空子数组数目 #前缀和 #哈希表 #线性DP

题目链接

题意

给定数组 nums(长度不大于\(1e5\)) 和一个整数 target 。现要返回 非空不重叠 子数组的最大数目,且每个子数组中数字和都为 target

样例

nums = [-1,3,5,1,4,2,-9], target = 6,总共有 3 个子数组和为 6 。 $([5,1], [4,2], [3,5,1,4,2,-9]) $但只有前 2 个是不重叠的。

分析

dp[i]表示前i位满足要求的数组个数;sum表示[1, size]的前缀和(先假定从1计数)

当\(i>0\)显然dp[0] = 0;当\(i>0\)时,有两种情况:

  • 存在这样的\(pos(\leq i) st.sum[i]-sum[pos]==target\),

    • 我们找到\([pos, i]\)的合法子数组,于是dp[i] 可以由dp[pos]+1转移
    • [pos, i]的子数组长度可能太长,以至于覆盖了该区间的几个合法子数组,那么dp[i]也可以由dp[i-1]转移

    即得到转移方程:\(dp[i] = max(dp[i-1], dp[pos]+1)\)

  • 不存在这样的\(pos\),显然转移方程只能为\(dp[i] = dp[i-1]\)

class Solution {
private:
int dp[100005] = {0};
public:
int maxNonOverlapping(vector<int>& nums, int target) {
map<int, int> mymap;
int sum = 0; mymap[0] = 0;
for (int i = 1; i <= nums.size(); i++) {
sum += nums[i - 1];
if (mymap.count(sum - target)) { //是否存在sum[pos]满足sum[i]-sum[pos]=target
int pos = mymap[sum - target];
dp[i] = max(dp[i - 1], dp[pos] + 1);
}
else {
dp[i] = dp[i - 1];
}
mymap[sum] = i; //记录前缀和sum的最新位置
}
return dp[nums.size()];
}
};

1547 切棍子的最小成本 #区间DP

题目链接

题意

给定长度为\(n\)个单位的木棍,及记录你要将棍子切开的位置数组\(cuts[i]\),现要你按\(cuts[i]\)记录的位置按一定顺序切割木棍,使得成本最小,并求其值。其中每次切割的成本是当前要切割的棍子的长度。

分析

显然是石子合并的变式,区间DP题,不过我们需要预处理下每个切割位置之间的长度(该位置的序号-前一位置的序号),同时将代价数组sum[]从1计数,便于DP

class Solution {
private:
int sum[105] = { 0 };
int dp[105][105];
public:
int cost(int lo, int hi) {
return sum[hi] - sum[lo];
}
void Init(int maxlen, vector<int>& cuts, int n) {
sort(cuts.begin(), cuts.end());
for (int i = 1; i <= maxlen; i++)
for (int j = 1; j <= maxlen; j++)
dp[i][j] = 0x3f3f3f3f;
sum[1] = cuts[0]; dp[1][1] = dp[maxlen][maxlen] = 0;
for (int i = 2; i <= cuts.size(); i++) {
dp[i][i] = 0;
sum[i] = sum[i - 1] + cuts[i - 1] - cuts[i - 2];
}
sum[maxlen] = sum[maxlen - 1] + n - cuts[cuts.size() - 1];
}
int minCost(int n, vector<int>& cuts) {
int maxlen = cuts.size() + 1;
Init(maxlen, cuts, n);
for (int len = 2; len <= maxlen; len++) {
for (int i = 1; i + len - 1 <= maxlen; i++) {
int j = i + len - 1;
for (int k = i; k < j; k++)
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + cost(i - 1, j));
}
}
return dp[1][maxlen];
}
};

Leetcode 周赛#201 题解的更多相关文章

  1. Leetcode 周赛#202 题解

    本周的周赛题目质量不是很高,因此只给出最后两题题解(懒). 1552 两球之间的磁力 #二分答案 题目链接 题意 有n个空篮子,第i个篮子位置为position[i],现希望将m个球放到这些空篮子,使 ...

  2. LeetCode周赛#204 题解

    1566. 重复至少 K 次且长度为 M 的模式 #模拟 题目链接 题意 给定正整数数组 arr,请你找出一个长度为 m 且在数组中至少重复 k 次的模式. 模式 是由一个或多个值组成的子数组(连续的 ...

  3. LeetCode周赛#203 题解

    1561. 你可以获得的最大硬币数目 #贪心 题目链接 题意 有 3n 堆数目不一的硬币,你和你的朋友们打算按以下方式分硬币: 每一轮中,你将会选出 任意 3 堆硬币(不一定连续). Alice 将会 ...

  4. Leetcode 周赛#200 题解

    1535 找出数组游戏的赢家 #模拟+优化 题目链接 题意 给你一个由 不同 整数组成的整数数组 arr 和一个整数 k(\(1\leq k\leq1e9\)) .每回合游戏都在数组的arr[0] 和 ...

  5. 【LeetCode】201. Bitwise AND of Numbers Range 解题报告(Python)

    [LeetCode]201. Bitwise AND of Numbers Range 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/prob ...

  6. LeetCode双周赛#33 题解

    5480. 可以到达所有点的最少点数目 #贪心 题目链接 题意 给定有向无环图,编号从0到n-1,一个边集数组edges(表示从某个顶点到另一顶点的有向边),现要找到最小的顶点集合,使得从这些点出发, ...

  7. Leetcode 双周赛#32 题解

    1540 K次操作转变字符串 #计数 题目链接 题意 给定两字符串\(s\)和\(t\),要求你在\(k\)次操作以内将字符串\(s\)转变为\(t\),其中第\(i\)次操作时,可选择如下操作: 选 ...

  8. 【Leetcode周赛】从contest-111开始。(一般是10个contest写一篇文章)

    Contest 111 (题号941-944)(2019年1月19日,补充题解,主要是943题) 链接:https://leetcode.com/contest/weekly-contest-111 ...

  9. 【Leetcode周赛】从contest-41开始。(一般是10个contest写一篇文章)

    Contest 41 ()(题号) Contest 42 ()(题号) Contest 43 ()(题号) Contest 44 (2018年12月6日,周四上午)(题号653—656) 链接:htt ...

随机推荐

  1. webpack 单独打包指定JS文件

    背景 最近接到一个需求,因为不确定打出的前端包所访问的后端IP,需要对项目中IP配置文件单独拿出来,方便运维部署的时候对IP做修改.因此,需要用webpack单独打包指定文件. CommonsChun ...

  2. nacos 作为配置中心使用心得--配置使用

    1.页面配置 撇开原理不谈,先来介绍下nacos的基本使用,如下图nacos配置是以data id为单位进行使用的,基本上一个服务的一个配置文件就对应一个data id,支持的格式有xml,yaml, ...

  3. Luogu P6280 [USACO20OPEN]Exercise G

    题意 定义一个长度为 \(n\) 的置换的步数为将 \(P=(1,2,\cdots,n)\) 在该置换操作下变回原样的最小次数. 求所有 \(K\) 的和,使得存在一个长度为 \(n\) 的置换使得其 ...

  4. Spring Cloud Alibaba 基础

    Spring Cloud Alibaba 基础 什么是Spring Cloud Alibaba 这里我们不讲解Spring Cloud 和 Spring Cloud Alibaba 的关系,大家自己查 ...

  5. MySQL中load data infile将文件中的数据批量导入数据库

    有时候我们需要将文件中的数据直接导入到数据库中,那么我们就可以使用load data infile,下面具体介绍使用方法. dao中的方法 @Autowired private JdbcTemplat ...

  6. ()C++中的赋值运算符重载函数(operator=)

    本文主要介绍C++中的重载操作符(operator)的相关知识. 概述 1.1 what operator 是C++的一个关键字,它和运算符(如=)一起使用,表示一个运算符重载函数,在理解时可将ope ...

  7. AES的数学基础

    有限域 有限域上的运算 加法 两个多项式进行加法运算,就是两个多项式对应系数模2相加 乘法 两个多项式进行乘法运算:两个多项式相乘 若运算结果超过7次方,则必须对此结果进行一个多项式m(x)模运算,其 ...

  8. webpack配置babel篇

    babel-polyfill & babel-runtime & babel-preset-env babel-core babel-core 的作用是把 js 代码分析成 ast , ...

  9. C++ 数据结构 4:排序

    1 基本概念 1.1 定义 排序是计算机内经常进行的一种操作,其目的是将一组"无序"的数据元素调整为"有序"的数据元素. 1.2 数学定义 假设含n个数据元素的 ...

  10. impala-shell -o a.txt 查询中有中文时报错问题的处理

    当使用impala-shell -o a.txt进入impala-shell之后,查询报错: 报错情况: Query: select * from dim_sales_dept Unknown Exc ...