LeetCode 777
链接:https://leetcode.com/problems/swap-adjacent-in-lr-string/
方法:双指针
时间复杂度:O(n)
想法:这题有点头脑风暴的感觉,说到算法倒是也没什么经典算法。还是靠观察题目的特殊性质,所以说start字符串里面的'L'可以穿越所有'X'往左移,'R'可以穿越所有'X'往右移。所以start可以转化成end的充要条件就是,1) start跟end里面的'L'和'R'相对顺序相同。2) 个数相同。3) start里面的'L'必须在end相对应的'L'的同位置或右边,'R'必须在end相对应的'R'的同位置或左边。所以直接两个指针分别指start和end,然后如果是'X'就一直往后挪,抓到不是'X'的地方来比一下。
代码:
class Solution {
public boolean canTransform(String start, String end) {
int n = start.length(), i = 0, j = 0;
while (i < n && j < n) {
while (i < n && start.charAt(i) == 'X') i++;
while (j < n && end.charAt(j) == 'X') j++;
if (i < n && j < n) {
if (start.charAt(i) != end.charAt(j)) {
return false;
}
if ((start.charAt(i) == 'L' && i < j) || (start.charAt(i) == 'R' && i > j)) {
return false;
}
}
else {
break;
}
i++;
j++;
}
while (i < n) {
if (start.charAt(i) != 'X') return false;
i++;
}
while (j < n) {
if (end.charAt(j) != 'X') return false;
j++;
}
return true;
}
}
LeetCode 698
链接:https://leetcode.com/problems/partition-to-k-equal-sum-subsets/
方法:DFS
时间复杂度:O(n!)
想法:这个题写DFS还是应该说是比较好写的,这个题值得讨论的其实就两点。
- 为什么不能写背包DP?
如果是问能不能分成两个equal sum subsets,那是可以用背包DP的,但是这个题是k个,就算用背包DP算出来可以达到sum/k,那也并没有多少用,一是背包DP不存储具体的存放方案,二是只达到了一个sum/k不够,没法论证其他的值可以等分成k-1份,而且做这样一次DP,问题变成“剩下的值等分成k-1份”,它没有比原问题简单多少,而做一次DP代价却不小,因此不这样做。 - 针对每一个target = sum / k做DFS的时候,需要注意什么?
正如常规的DFS,我们肯定会开一个visited数组,但这里是这样,对每一个target = sum / k做DFS的时候,我们还需要一个index,表示我们目前扫描到哪了,不能每次都从0开始。这个地方就像是不考虑visited这个数组,我们做组合型DFS的时候的做法。
代码:
class Solution {
public boolean canPartitionKSubsets(int[] nums, int k) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if (sum % k != 0) {
return false;
}
boolean[] visited = new boolean[nums.length];
return dfs(nums, k, 0, sum / k, visited, 0);
}
private boolean dfs(int[] nums, int k, int cur, int target, boolean[] visited, int index) {
if (k == 1) {
return true;
}
if (cur == target) {
return dfs(nums, k - 1, 0, target, visited, 0);
}
for (int i = index; i < nums.length; i++) {
if (!visited[i] && nums[i] + cur <= target) {
visited[i] = true;
if (dfs(nums, k, cur + nums[i], target, visited, i + 1)) {
return true;
}
visited[i] = false;
}
}
return false;
}
}