描述:给你一个长度为 n 的字符串 moves ,该字符串仅由字符 ‘L’、‘R’ 和 ‘_’ 组成。字符串表示你在一条原点为 0 的数轴上的若干次移动。
你的初始位置就在原点(0),第 i 次移动过程中,你可以根据对应字符选择移动方向:
如果 moves[i] = ‘L’ 或 moves[i] = ‘’ ,可以选择向左移动一个单位距离
如果 moves[i] = ‘R’ 或 moves[i] = '’ ,可以选择向右移动一个单位距离
移动 n 次之后,请你找出可以到达的距离原点 最远 的点,并返回 从原点到这一点的距离 。
示例 1:
输入:moves = "L_RL__R"
输出:3
解释:可以到达的距离原点 0 最远的点是 -3 ,移动的序列为 "LLRLLLR" 。
示例 2:
输入:moves = "_R__LL_"
输出:5
解释:可以到达的距离原点 0 最远的点是 -5 ,移动的序列为 "LRLLLLL" 。
示例 3:
输入:moves = "_______"
输出:7
解释:可以到达的距离原点 0 最远的点是 7 ,移动的序列为 "RRRRRRR" 。
提示:
1 <= moves.length == n <= 50
moves 仅由字符 ‘L’、‘R’ 和 ‘_’ 组成
思路:脑筋急转弯,将直观模拟转换为求解L和R数量,因为L和R可以抵消,故可以将_转换为L和R较多的那个再进行求解。
class Solution {
public:
int furthestDistanceFromOrigin(string moves) {
int n=moves.size();
// l表示L数量 r表示R数量
int l=0,r=0;
// 转化为l与r抵消剩余多少则往哪个方向移动
for(auto move:moves)
{
if(move=='R')
r++;
if(move=='L')
l++;
}
return l>r?n-2*r:n-2*l;
}
};
总结:首先是理解题意,然后是直观模拟,当直观模拟较为复杂,则考虑在不改变结果的情况下如何转换求解以便优化时空复杂度。
描述:给你两个正整数:n 和 target 。
如果数组 nums 满足下述条件,则称其为 美丽数组 。
nums.length == n.
nums 由两两互不相同的正整数组成。
在范围 [0, n-1] 内,不存在 两个 不同 下标 i 和 j ,使得 nums[i] + nums[j] == target 。
返回符合条件的美丽数组所可能具备的 最小 和。
示例 1:
输入:n = 2, target = 3
输出:4
解释:nums = [1,3] 是美丽数组。
- nums 的长度为 n = 2 。
- nums 由两两互不相同的正整数组成。
- 不存在两个不同下标 i 和 j ,使得 nums[i] + nums[j] == 3 。
可以证明 4 是符合条件的美丽数组所可能具备的最小和。
示例 2:
输入:n = 3, target = 3
输出:8
解释:
nums = [1,3,4] 是美丽数组。
- nums 的长度为 n = 3 。
- nums 由两两互不相同的正整数组成。
- 不存在两个不同下标 i 和 j ,使得 nums[i] + nums[j] == 3 。
可以证明 8 是符合条件的美丽数组所可能具备的最小和。
示例 3:
输入:n = 1, target = 1
输出:1
解释:nums = [1] 是美丽数组。
提示:
1 <= n <= 105
1 <= target <= 105
思路:最开始是一种很神奇的感觉,没有说那种脑海中浮现出很直观的清晰的逻辑思路,但是写着写着就写出来了。贪心想法,必定是按照1、2、3…n的顺序得到的数组和最小,而且1必定在结果中,所以使用uset存储已经加入结果集合,初始为1,使用num表示当前加入元素,初始为2,使用res表示当前数组和,初始为1,当在uset中找不到与num相加和为target的元素时则将num加入uset并更新数组和res。
class Solution {
public:
long long minimumPossibleSum(int n, int target) {
// 长度为1的数组最小为1
if(n==1)
return 1;
// 记录元素和 1肯定在
long long res=1;
// 记录加入元素
unordered_set uset;
uset.emplace(1);
// 记录当前加入元素
int num=2;
// 1 2 3 4依次加入最小 按照target排除不能加入元素 使用uset记录已经加入元素
while(uset.size()
优化:当时在模拟示例数据时,想到对于元素和target,在和为target的两两配对中必定选取较小的那个数,而对于大于等于target的数选择部分数使得总数据数量为n。
class Solution {
public:
long long minimumPossibleSum(int n, int target) {
// 第一部分:两两配对中取较小者 1、2、3...k/2 使得n>=m
long long m=min(target/2,n);
// 第二部分:剩余n-m个数 k...k+n-m-1 如果最小m为n 那么后者为0
return (m*(m+1)+(target*2+n-m-1)*(n-m))/2;
}
};
PS:后两题不会hhh,有时候想想刷题真神奇,因为无论如何都不会到达天花板,总是会在某些题中找到无力感和挫败感,但是又有什么办法呢,感觉还是多总结多思考,不断积累思路,然后形成知识体系,总有一天会blingblingbling的吧~~