Leetcode每日一题 —— 657. 机器人能否返回原点
- 内容介绍
- 文章标签
- 相关推荐
657. 机器人能否返回原点 - 力扣(LeetCode)
657. 机器人能否返回原点 - 在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在(0, 0) 处结束。 移动顺序由字符串moves表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有R(右),L(左),U(上)和 D(下)。 如果机器人在完成所有动作后返回原点,则返回 true。否则,返回 false。 注意:机器人“面朝”的方向无关紧要。 “R” 将始终使机器人向右移动一次,“L”...
依旧机器人 (¬`‸´¬)
思路
其实就是简单的模拟题,根据操作模拟左右上下移动、更新坐标,最终判断是否回到原点即可。
代码
20. 有效的括号 - 力扣(LeetCode) 155. 最小栈 - 力扣(LeetCode) 33. 搜索旋转排序数组 - 力扣(LeetCode) 这题每次剪枝时要考虑两点: 可以发现,二分得到 这个时候就可以利用首个元素 找到升序序列后,判断 这样不停更新边界来逼近这个 56. 合并区间 - 力扣(LeetCode)class Solution {
public:
bool judgeCircle(string moves) {
// 模拟题
int xPos=0,yPos=0;
for(char c:moves){
switch(c){
case 'R':
xPos++;
break;
case 'L':
xPos--;
break;
case 'U':
yPos++;
break;
case 'D':
yPos--;
break;
}
}
return xPos==0 && yPos==0;
}
};
然后就是继续复习 Hot100
class Solution {
public:
bool isValid(string s) {
// 用栈即可
stack<char> stk;
for(char c:s){
switch(c){
case ')':
if(stk.empty()||stk.top()!='('){
return false;
}
stk.pop();
break;
case '}':
if(stk.empty()||stk.top()!='{'){
return false;
}
stk.pop();
break;
case ']':
if(stk.empty()||stk.top()!='['){
return false;
}
stk.pop();
break;
default:
stk.emplace(c);
}
}
// 注意最后栈不能为空
return stk.empty();
}
};
class MinStack {
private:
vector<pair<int,int>> stk;
public:
MinStack() {
// 这题难点就是常数时间拿到最小元素
// 一个很巧的思路就是,每个入栈的元素都记录当前最小的元素
}
void push(int val) {
int currMin=val;
if(!stk.empty()){
// 如果有栈顶,就和上一个最小值状态进行比较看谁更小
currMin=stk.back().second;
}
currMin=min(currMin,val);
stk.emplace_back(make_pair(val,currMin));
}
void pop() {
stk.pop_back();
}
int top() {
return stk.back().first;
}
int getMin() {
return stk.back().second;
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
target 在不在这个有序序列中?mid 下标后,这个下标必然属于一个有序序列。数组可能因为旋转变成两个有序序列,那么 mid 就肯定在其中一个序列中。nums[0],如果大于 nums[0],说明 [0, mid] 范围的序列是升序,否则是 [mid, n-1]。target 在不在这个序列中,如果在,则看是左边的有序序列还是右边的有序序列,如果是左边的,那为了逼近 target,就应该左移右边界;反之就是右移左边界。target,注意外层是在和数组首个元素比较,不同于以往是在和 target 比。class Solution {
public:
int search(vector<int>& nums, int target) {
// 旋转后数组可能被截成两段升序序列
// 此时首个元素和最后一个元素就有特殊的意义了
// 小于首个元素,说明在数组右侧
// 大于首个元素则在左侧
int l=0,r=nums.size()-1;
while(l<=r){
int mid=(l+r)>>1;
if(nums[mid]==target){
return mid;
}else if(nums[mid]>=nums[0]){
// 如果比首个元素大,说明 [0, mid] 是有序序列
if(nums[0]<=target&&target<=nums[mid]){
// 如果 target 在这个有序序列中,就收缩右边界
// 已知 target 不会是 nums[mid]
r=mid-1;
}else{
// 否则 target 在另一侧
l=mid+1;
}
}else if(nums[mid]<nums[0]){
// 如果比首个元素小,则 [mid, n-1] 是有序序列
if(nums[mid]<=target&&target<=nums[nums.size()-1]){
// target 在这个有序序列中,收缩左边界
// 已知 target 不会是 nums[mid]
l=mid+1;
}else{
// 否则 target 在另一侧
r=mid-1;
}
}
}
return -1;
}
};
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
// 按 start 对 intervals 进行排序后合并即可
sort(intervals.begin(),intervals.end(),[](const auto& a, const auto& b){
return a[0]<b[0];
});
vector<vector<int>> res;
// 存储上一个区间的结束位置
int lastEnd=-1;
for(vector<int>& itv:intervals){
if(lastEnd>=itv[1]){
// 当前区间被上一个区间包含进去了
continue;
}
if(lastEnd>=itv[0]){
// 上一个区间的结束位置 >= 当前区间的开始位置,合并
lastEnd=itv[1];
res[res.size()-1][1]=lastEnd;
}else{
// 否则独立成为一个新区间
lastEnd=itv[1];
res.emplace_back(itv);
}
}
return res;
}
};
--【壹】--:
简单题。
class Solution {
public:
bool judgeCircle(string moves) {
return !(std::count(moves.begin(),moves.end(),'L') - std::count(moves.begin(),moves.end(),'R'))
& !(std::count(moves.begin(),moves.end(),'U') - std::count(moves.begin(),moves.end(),'D'));
}
};
657. 机器人能否返回原点 - 力扣(LeetCode)
657. 机器人能否返回原点 - 在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在(0, 0) 处结束。 移动顺序由字符串moves表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有R(右),L(左),U(上)和 D(下)。 如果机器人在完成所有动作后返回原点,则返回 true。否则,返回 false。 注意:机器人“面朝”的方向无关紧要。 “R” 将始终使机器人向右移动一次,“L”...
依旧机器人 (¬`‸´¬)
思路
其实就是简单的模拟题,根据操作模拟左右上下移动、更新坐标,最终判断是否回到原点即可。
代码
20. 有效的括号 - 力扣(LeetCode) 155. 最小栈 - 力扣(LeetCode) 33. 搜索旋转排序数组 - 力扣(LeetCode) 这题每次剪枝时要考虑两点: 可以发现,二分得到 这个时候就可以利用首个元素 找到升序序列后,判断 这样不停更新边界来逼近这个 56. 合并区间 - 力扣(LeetCode)class Solution {
public:
bool judgeCircle(string moves) {
// 模拟题
int xPos=0,yPos=0;
for(char c:moves){
switch(c){
case 'R':
xPos++;
break;
case 'L':
xPos--;
break;
case 'U':
yPos++;
break;
case 'D':
yPos--;
break;
}
}
return xPos==0 && yPos==0;
}
};
然后就是继续复习 Hot100
class Solution {
public:
bool isValid(string s) {
// 用栈即可
stack<char> stk;
for(char c:s){
switch(c){
case ')':
if(stk.empty()||stk.top()!='('){
return false;
}
stk.pop();
break;
case '}':
if(stk.empty()||stk.top()!='{'){
return false;
}
stk.pop();
break;
case ']':
if(stk.empty()||stk.top()!='['){
return false;
}
stk.pop();
break;
default:
stk.emplace(c);
}
}
// 注意最后栈不能为空
return stk.empty();
}
};
class MinStack {
private:
vector<pair<int,int>> stk;
public:
MinStack() {
// 这题难点就是常数时间拿到最小元素
// 一个很巧的思路就是,每个入栈的元素都记录当前最小的元素
}
void push(int val) {
int currMin=val;
if(!stk.empty()){
// 如果有栈顶,就和上一个最小值状态进行比较看谁更小
currMin=stk.back().second;
}
currMin=min(currMin,val);
stk.emplace_back(make_pair(val,currMin));
}
void pop() {
stk.pop_back();
}
int top() {
return stk.back().first;
}
int getMin() {
return stk.back().second;
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
target 在不在这个有序序列中?mid 下标后,这个下标必然属于一个有序序列。数组可能因为旋转变成两个有序序列,那么 mid 就肯定在其中一个序列中。nums[0],如果大于 nums[0],说明 [0, mid] 范围的序列是升序,否则是 [mid, n-1]。target 在不在这个序列中,如果在,则看是左边的有序序列还是右边的有序序列,如果是左边的,那为了逼近 target,就应该左移右边界;反之就是右移左边界。target,注意外层是在和数组首个元素比较,不同于以往是在和 target 比。class Solution {
public:
int search(vector<int>& nums, int target) {
// 旋转后数组可能被截成两段升序序列
// 此时首个元素和最后一个元素就有特殊的意义了
// 小于首个元素,说明在数组右侧
// 大于首个元素则在左侧
int l=0,r=nums.size()-1;
while(l<=r){
int mid=(l+r)>>1;
if(nums[mid]==target){
return mid;
}else if(nums[mid]>=nums[0]){
// 如果比首个元素大,说明 [0, mid] 是有序序列
if(nums[0]<=target&&target<=nums[mid]){
// 如果 target 在这个有序序列中,就收缩右边界
// 已知 target 不会是 nums[mid]
r=mid-1;
}else{
// 否则 target 在另一侧
l=mid+1;
}
}else if(nums[mid]<nums[0]){
// 如果比首个元素小,则 [mid, n-1] 是有序序列
if(nums[mid]<=target&&target<=nums[nums.size()-1]){
// target 在这个有序序列中,收缩左边界
// 已知 target 不会是 nums[mid]
l=mid+1;
}else{
// 否则 target 在另一侧
r=mid-1;
}
}
}
return -1;
}
};
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
// 按 start 对 intervals 进行排序后合并即可
sort(intervals.begin(),intervals.end(),[](const auto& a, const auto& b){
return a[0]<b[0];
});
vector<vector<int>> res;
// 存储上一个区间的结束位置
int lastEnd=-1;
for(vector<int>& itv:intervals){
if(lastEnd>=itv[1]){
// 当前区间被上一个区间包含进去了
continue;
}
if(lastEnd>=itv[0]){
// 上一个区间的结束位置 >= 当前区间的开始位置,合并
lastEnd=itv[1];
res[res.size()-1][1]=lastEnd;
}else{
// 否则独立成为一个新区间
lastEnd=itv[1];
res.emplace_back(itv);
}
}
return res;
}
};
--【壹】--:
简单题。
class Solution {
public:
bool judgeCircle(string moves) {
return !(std::count(moves.begin(),moves.end(),'L') - std::count(moves.begin(),moves.end(),'R'))
& !(std::count(moves.begin(),moves.end(),'U') - std::count(moves.begin(),moves.end(),'D'));
}
};

