数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1
输出:["()"]
提示:
1 <= n <= 8
Python 3
class Solution:
# 方法1: 递归法
# 时间复杂度: O(2^(2n) * n)
# 空间复杂度: O(n)
def generateParenthesis(self, n: int) -> List[str]:
def generate(A):
if len(A) == 2*n:
if valid(A):
ans.append("".join(A))
else:
A.append('(')
generate(A)
A.pop()
A.append(')')
generate(A)
A.pop()
def valid(A):
bal = 0
for c in A:
if c == '(': bal += 1
else: bal -= 1
if bal < 0: return False
return bal == 0
ans = []
generate([])
return ans
给你一个 升序排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k
个元素,那么 nums
的前 k
个元素应该保存最终结果。
将最终结果插入 nums
的前 k
个位置后返回 k
。
不要使用额外的空间,你必须在 原地修改输入数组 并在使用 O(1) 额外空间的条件下完成。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
提示:
C
// 方法1:双指针:快慢指针
int removeDuplicates(int* nums, int numsSize) {
if (numsSize < 2) {
return numsSize;
}
// i 指向当前正比较的两个相邻的两个元素
// j 指向无重复的最后一个元素
int i = 1, j = 1;
while (i + 1 <= numsSize) {
// 注意:数组最大下标值 + 1 = 数组长度,还有个 -1 (<=)是因为防止下面的-1越界
if (nums[i - 1] != nums[i]) {
nums[j] = nums[i];
j++;
}
i++;
}
return j;
}
假设你正在爬楼梯。需要 n
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
提示:
1 <= n <= 45
其实就是 动态规划 将 本问题 分解为 多个 子问题, 爬上 第 n 阶楼梯的方法数量 等于以下 两 部分之和 1. 爬上
n-1
阶楼梯的方法数量, 因为再爬1阶就能到第 n 阶 2. 爬上n-2
阶楼梯的方法数量, 因为再爬2阶就能到第 n 阶 于是可得
public class Solution {
#region 方法2: 循环
public int ClimbStairs(int n)
{
if (n <= 1)
{
return 1;
}
// 注意: 长度: n + 1
int[] arr = new int[n + 1];
arr[0] = 1;
arr[1] = 1;
for (int i = 2; i < arr.Length; i++)
{
// arr[2] = arr[1] + arr[0]
// arr[3] = arr[2] + arr[1]
// arr[4] = arr[3] + arr[2]
// ...
// 在循环内最后一次: 再i++, 就会达到 Length, 从而不满足循环条件而退出
// arr[n] = arr[n - 1] + arr[n -2]
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr[n];
}
#endregion
}
public class Solution {
#region 方法3: 循环 压缩优化
/// <summary>
/// dp[i] 只与 dp[i - 1] 和 dp[i - 2] 有关,没有必要存储所有计算过的 dp 项。用两个临时变量去存这两个状态就好
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
public int ClimbStairs(int n)
{
int prev = 1, cur = 1;
int temp;
for (int i = 2; i < n + 1; i++)
{
temp = cur; // 暂存上一次的 cur
cur = prev + cur; // 当前的 cur = 上上次cur + 上一次cur
prev = temp; // prev 更新为 上一次 cur
}
return cur;
}
#endregion
}
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n)
的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
class Solution {
public int searchInsert(int[] nums, int target) {
int n = nums.length;
int left = 0, right = n - 1, ans = n;
while(left <= right) {
int mid = ((right - left)>>1)+ left;
if(target <= nums[mid]) {
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
}
}
给你两个按 非递减顺序 排列的整数数组 nums1
和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。
请你 合并 nums2
到 nums1
中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1
中。为了应对这种情况,nums1
的初始长度为 m + n
,其中前 m
个元素表示应合并的元素,后 n
个元素为 0
,应忽略。nums2
的长度为 n
。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-10<sup>9</sup> <= nums1[i], nums2[j] <= 10<sup>9</sup>
进阶: 你可以设计实现一个时间复杂度为 O(m + n)
的算法解决此问题吗?
public class Solution {
#region 方法一:双指针/从前往后
/// <summary>
/// https://leetcode-cn.com/problems/merge-sorted-array/solution/he-bing-liang-ge-you-xu-shu-zu-by-leetco-qn2i/
/// </summary>
/// <param name="nums1"></param>
/// <param name="m"></param>
/// <param name="nums2"></param>
/// <param name="n"></param>
public void Merge(int[] nums1, int m, int[] nums2, int n)
{
int p1 = 0, p2 = 0;
int[] sorted = new int[m + n];
int cur;
while (p1 < m || p2 < n)
{
if (p1 == m)
{
cur = nums2[p2++];
}
else if (p2 == n)
{
cur = nums1[p1++];
}
else if (nums1[p1] < nums2[p2])
{
cur = nums1[p1++];
}
else
{
cur = nums2[p2++];
}
sorted[p1 + p2 - 1] = cur;
}
for (int i = 0; i != m + n; i++)
{
nums1[i] = sorted[i];
}
}
#endregion
}
感谢帮助!