Skip to content

Commit 5650538

Browse files
committed
feat: Add solution for LeetCode #1545
1 parent e523e61 commit 5650538

4 files changed

Lines changed: 179 additions & 0 deletions

File tree

SOLVED.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@
173173
| 1534 | [Count Good Triplets](https://leetcode.com/problems/count-good-triplets/) | [Code](src/leetcode/problems/count-good-triplets.cpp) / [Test](test/leetcode/problems/count-good-triplets.cpp) |
174174
| 1536 | [Minimum Swaps to Arrange a Binary Grid](https://leetcode.com/problems/minimum-swaps-to-arrange-a-binary-grid/) | [Code](src/leetcode/problems/minimum-swaps-to-arrange-a-binary-grid.cpp) / [Test](test/leetcode/problems/minimum-swaps-to-arrange-a-binary-grid.cpp) |
175175
| 1544 | [Make The String Great](https://leetcode.com/problems/make-the-string-great/) | [Code](src/leetcode/problems/make-the-string-great.cpp) / [Test](test/leetcode/problems/make-the-string-great.cpp) |
176+
| 1545 | [Find Kth Bit in Nth Binary String](https://leetcode.com/problems/find-kth-bit-in-nth-binary-string/) | [Code](src/leetcode/problems/find-kth-bit-in-nth-binary-string.cpp) / [Test](test/leetcode/problems/find-kth-bit-in-nth-binary-string.cpp) |
176177
| 1550 | [Three Consecutive Odds](https://leetcode.com/problems/three-consecutive-odds/) | [Code](src/leetcode/problems/three-consecutive-odds.cpp) / [Test](test/leetcode/problems/three-consecutive-odds.cpp) |
177178
| 1559 | [Detect Cycles in 2D Grid](https://leetcode.com/problems/detect-cycles-in-2d-grid/) | [Code](src/leetcode/problems/detect-cycles-in-2d-grid.cpp) / [Test](test/leetcode/problems/detect-cycles-in-2d-grid.cpp) |
178179
| 1572 | [Matrix Diagonal Sum](https://leetcode.com/problems/matrix-diagonal-sum/) | [Code](src/leetcode/problems/matrix-diagonal-sum.cpp) / [Test](test/leetcode/problems/matrix-diagonal-sum.cpp) |
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "leetcode/core.h"
2+
3+
namespace leetcode {
4+
namespace problem_1545 {
5+
6+
using Func = std::function<char(int, int)>;
7+
8+
class FindKthBitInNthBinaryStringSolution : public SolutionBase<Func> {
9+
public:
10+
char findKthBit(int n, int k);
11+
12+
FindKthBitInNthBinaryStringSolution();
13+
};
14+
15+
} // namespace problem_1545
16+
} // namespace leetcode
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include "leetcode/problems/find-kth-bit-in-nth-binary-string.h"
2+
3+
namespace leetcode {
4+
namespace problem_1545 {
5+
6+
/**
7+
* 递归分治解法
8+
*
9+
* Sₙ 的结构分析:
10+
* Sₙ = Sₙ₋₁ + "1" + reverse(invert(Sₙ₋₁))
11+
* 长度:len(Sₙ) = 2ⁿ - 1 = (2ⁿ⁻¹ - 1) + 1 + (2ⁿ⁻¹ - 1)
12+
*
13+
* 对于第 k 位:
14+
* - 如果 k == 2ⁿ⁻¹,返回 "1"
15+
* - 如果 k < 2ⁿ⁻¹,在 Sₙ₋₁ 中找第 k 位
16+
* - 如果 k > 2ⁿ⁻¹,在 reverse(invert(Sₙ₋₁)) 中找第 k - 2ⁿ⁻¹ 位
17+
* 这等于在 invert(Sₙ₋₁) 中找倒数第 (k - 2ⁿ⁻¹) 位
18+
* 即 Sₙ₋₁ 的正数第 (2ⁿ⁻¹ - (k - 2ⁿ⁻¹)) = (2ⁿ - k) 位取反
19+
*
20+
* 时间复杂度: O(n),每次递归 n 减 1
21+
* 空间复杂度: O(n),递归栈深度
22+
*/
23+
static char solution1(int n, int k) {
24+
// 递归辅助函数,flip 表示当前位需要翻转的次数(0 或 1)
25+
function<char(int, int, int)> dfs = [&](int n, int k, int flip) -> char {
26+
if (n == 1) {
27+
// S₁ = "0"
28+
return flip ? '1' : '0';
29+
}
30+
31+
int mid = 1 << (n - 1); // 2ⁿ⁻¹,中间位置(Sₙ 的正中间是第 2ⁿ⁻¹ 位)
32+
33+
if (k == mid) {
34+
// 中间位置,固定是 "1"
35+
return flip ? '0' : '1';
36+
} else if (k < mid) {
37+
// 在左半部分 Sₙ₋₁ 中
38+
return dfs(n - 1, k, flip);
39+
} else {
40+
// 在右半部分 reverse(invert(Sₙ₋₁)) 中
41+
// 第 k 位对应于 Sₙ₋₁ 的第 (2ⁿ - k) 位取反
42+
// 取反通过 flip 的奇偶性来传递
43+
return dfs(n - 1, (1 << n) - k, flip ^ 1);
44+
}
45+
};
46+
47+
return dfs(n, k, 0);
48+
}
49+
50+
/**
51+
* 迭代版本(避免递归开销)
52+
* 时间复杂度: O(n)
53+
* 空间复杂度: O(1)
54+
*/
55+
static char solution2(int n, int k) {
56+
int flip = 0;
57+
58+
while (n > 1) {
59+
int mid = 1 << (n - 1); // 2ⁿ⁻¹
60+
61+
if (k == mid) {
62+
// 中间位置,固定是 "1"
63+
return flip ? '0' : '1';
64+
} else if (k > mid) {
65+
// 在右半部分,需要取反,并映射到对称位置
66+
k = (1 << n) - k;
67+
flip ^= 1;
68+
}
69+
// 如果在左半部分,直接继续,n 减 1
70+
n--;
71+
}
72+
73+
// n == 1,S₁ = "0"
74+
return flip ? '1' : '0';
75+
}
76+
77+
FindKthBitInNthBinaryStringSolution::FindKthBitInNthBinaryStringSolution() {
78+
setMetaInfo({
79+
.id = 1545,
80+
.title = "Find Kth Bit in Nth Binary String",
81+
.url = "https://leetcode.com/problems/find-kth-bit-in-nth-binary-string/"
82+
});
83+
registerStrategy("Recursive", solution1);
84+
registerStrategy("Iterative", solution2);
85+
}
86+
87+
char FindKthBitInNthBinaryStringSolution::findKthBit(int n, int k) {
88+
return getSolution()(n, k);
89+
}
90+
91+
} // namespace problem_1545
92+
} // namespace leetcode
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include "leetcode/problems/find-kth-bit-in-nth-binary-string.h"
2+
3+
#include "gtest/gtest.h"
4+
5+
namespace leetcode {
6+
namespace problem_1545 {
7+
8+
class FindKthBitInNthBinaryStringTest : public ::testing::TestWithParam<std::string> {
9+
protected:
10+
void SetUp() override { solution.setStrategy(GetParam()); }
11+
12+
FindKthBitInNthBinaryStringSolution solution;
13+
};
14+
15+
TEST_P(FindKthBitInNthBinaryStringTest, Example1) {
16+
// n = 3, k = 1, S₃ = "0111001", 第1位是 "0"
17+
EXPECT_EQ('0', solution.findKthBit(3, 1));
18+
}
19+
20+
TEST_P(FindKthBitInNthBinaryStringTest, Example2) {
21+
// n = 4, k = 11, S₄ = "011100110110001", 第11位是 "1"
22+
EXPECT_EQ('1', solution.findKthBit(4, 11));
23+
}
24+
25+
TEST_P(FindKthBitInNthBinaryStringTest, MiddlePosition) {
26+
// 测试中间位置,应该是 "1"
27+
// S₂ = "011", 中间位置 k = 2
28+
EXPECT_EQ('1', solution.findKthBit(2, 2));
29+
// S₃ = "0111001", 中间位置 k = 4
30+
EXPECT_EQ('1', solution.findKthBit(3, 4));
31+
}
32+
33+
TEST_P(FindKthBitInNthBinaryStringTest, LastPosition) {
34+
// 测试最后一个位置
35+
// S₂ = "011", 最后一位 k = 3 是 "1"
36+
EXPECT_EQ('1', solution.findKthBit(2, 3));
37+
// S₃ = "0111001", 最后一位 k = 7 是 "1"
38+
EXPECT_EQ('1', solution.findKthBit(3, 7));
39+
}
40+
41+
TEST_P(FindKthBitInNthBinaryStringTest, FirstPosition) {
42+
// S₁ = "0", 第一位 k = 1 是 "0"
43+
EXPECT_EQ('0', solution.findKthBit(1, 1));
44+
// Sₙ 的第一位总是 "0"
45+
EXPECT_EQ('0', solution.findKthBit(5, 1));
46+
EXPECT_EQ('0', solution.findKthBit(10, 1));
47+
}
48+
49+
TEST_P(FindKthBitInNthBinaryStringTest, SmallCases) {
50+
// S₂ = "011"
51+
EXPECT_EQ('0', solution.findKthBit(2, 1));
52+
EXPECT_EQ('1', solution.findKthBit(2, 2));
53+
EXPECT_EQ('1', solution.findKthBit(2, 3));
54+
55+
// S₃ = "0111001"
56+
EXPECT_EQ('0', solution.findKthBit(3, 1));
57+
EXPECT_EQ('1', solution.findKthBit(3, 2));
58+
EXPECT_EQ('1', solution.findKthBit(3, 3));
59+
EXPECT_EQ('1', solution.findKthBit(3, 4));
60+
EXPECT_EQ('0', solution.findKthBit(3, 5));
61+
EXPECT_EQ('0', solution.findKthBit(3, 6));
62+
EXPECT_EQ('1', solution.findKthBit(3, 7));
63+
}
64+
65+
INSTANTIATE_TEST_SUITE_P(
66+
LeetCode, FindKthBitInNthBinaryStringTest,
67+
::testing::ValuesIn(FindKthBitInNthBinaryStringSolution().getStrategyNames()));
68+
69+
} // namespace problem_1545
70+
} // namespace leetcode

0 commit comments

Comments
 (0)