顺时针打印矩阵.
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res; //记录遍历
if(matrix.empty()) return res;
int n = matrix.size(), m = matrix[0].size(); //横纵坐标
vector<vector<bool>> st(n, vector<bool>(m, false)); //记录是否遍历过
//上、右、下、左四种走向
int dx[] = {-1, 0, 1, 0}, dy[] = {0 , 1 , 0 , -1};
//初始值从【0,0】开始走
int x = 0, y = 0, d = 1;
for(int i = 0;i < n * m; i++) //循环走n * m次表示走完了
{
res.push_back(matrix[x][y]);//记录
st[x][y] = true; //标记
int a = x + dx[d], b = y + dy[d];
//下次走
if(a < 0 || a >= n || b < 0 || b >= m || st[a][b])
//如果实际的坐标不合法或者已经走过,那么就需要重新调整走向并
//确定新的位置
{
d = (d + 1) % 4; //调整走向
a = x + dx[d], b = y + dy[d]; //重新确定位置
}
x = a, y = b;
}
return res;
}
};
螺旋矩阵
类似的一道题也可以使用这个解法去处理螺旋矩阵.
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
if(!matrix.size()) return res;
int n = matrix.size(), m = matrix[0].size();
vector<vector<bool>> st(n, vector<bool>(m, false));
//上右下左
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int x = 0, y = 0, d = 1;
for(int i = 0;i < n * m; i++)
{
res.push_back(matrix[x][y]);//存放答案
st[x][y] = true;//标记为走过
int a = x + dx[d], b = y + dy[d];
if(a < 0 || a >= n || b < 0 || b >= m || st[a][b]){
d = (d + 1) % 4; //重新调整走向
a = dx[d] + x, b = dy[d] + y;//确定新的坐标
}
x = a, y = b;
}
return res;
}
};
栈的压入、弹出序列.
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
//长度不一样肯定不相等
if(pushed.size() != popped.size()) return false;
stack<int> st;
int i = 0;
for(const auto &ref : pushed)
{
st.push(ref);
//如果栈顶元素跟popped容器中的某一元素相同那么就出栈
while(i < popped.size() && st.size() && st.top() == popped[i])
{
st.pop();
i++;
}
}
return st.empty();
}
};
验证栈序列.
此题与上面那道题也是一样的解法,这里不得不吐槽力扣的重复题真是多,读者了解即可
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
if(pushed.size() != popped.size()) return false;
int i = 0;
stack<int> st;
for(auto &ref : pushed)
{
st.push(ref);
while(i < popped.size() && st.size() && st.top() == popped[i]) st.pop(), i++;
}
return st.empty();
}
};
核心思想为使用一个指针从前往后逐个检查字符串中的字符是否合法,如果合法,则指针后移,否则指针停止移动,显然如果字符串是合法的,这个指针应该移动到字符串的最末尾
同时在移动指针的过程中判断从字符串开始到当前位置的字符子串是否是合法的数值,并将它存储在isNum中,显然isNum记录了指针所指位置的字符子串是否能表示为数值的信息
class Solution {
public:
/*
解题思路:
首先为了能够区分i指针遍历到字符串结尾位置时就表示字符串是合法的,可以追加一个‘\0’在字符串的结
尾位置(表示遍历到该位置时字符串就是合法的),字符串的前面空格和末尾空格都要处理(跳过忽略),
紧接着要把不包含e的所有数字字符串处理,那么剩余的情况就是包含数字和e的情况了分开处理
总结:
1、加法减法符号忽略,因为是合法的
2、空格忽略,数字判断并不需要包含空格
3、判断字符串合法的方式是看i指针知否走到‘\0’位置处
4、字符串中数字字符包含e和不好含e要分情况看待
*/
bool isNumber(string s) {
bool isNum = false; //默认为fasle
//删除前后空格
int i = 0, j = s.size() - 1;
while(i < s.size() && s[i] == ' ') i++;
while(j >= 0 && s[j] == ' ') j--;
//为字符串末尾位置加上‘\0’,为字符串合法标记
s[j + 1] = '\0';
//将所有的加减法符号和数字小数点的情况包含进来比如: +1.34、+.12345
if(s[i] == '+' || s[i] == '-') i++;
//判断数字字符
while(s[i] >= '0' && s[i] <= '9')
{
isNum = true;
i++;
}
//处理小数点
if(s[i] == '.') i++;
//小数点后面为数字
while(s[i] >= '0' && s[i] <= '9')
{
isNum = true;
i++;
}
//以上已经把不包含e/E的情况给处理了,那么剩下的就是包含小数点和e(又或者e之后会有数字那么该字
//符串一定是合法的)
if(isNum && (s[i] == 'e' || s[i] == 'E'))
{
isNum = false; //字符串中出现e默认将isNum值设置为false,防止isNum后面没有数字
i++;
if(s[i] == '+' || s[i] == '-') i++;//忽略加法减法符号,因为是合法的
//判断e后面是否会出现数字字符,如果出现数字字符那么该字符串又是属于合法的了
while(s[i] >= '0' && s[i] <= '9')
{
isNum = true;
i++;
}
}
return (isNum && s[i] == '\0');
//如果i指针遍历字符串的过程中没有出现意外的情况,那么i指针一定会走到字符串的结尾位置,并且isNum的值一定是true
}
};
把字符串转换成整数.
class Solution {
public:
int strToInt(string str) {
int i = 0;
while(i < str.size() && str[i] == ' ') ++i;//跳过所有的空格
long ret = 0;
bool isminus = false; //假设正数
if(str[i] == '-' || str[i] == '+'){
if(str[i] == '-') isminus = true; //如果出现-号就标记为负数
++i;
}
long long res = 0;
while(str[i] >= '0' && str[i] <= '9'){
ret = ret * 10 + str[i] - '0'; //将剩余的数字字符转换为数字
++i;
if(!isminus && ret > INT_MAX) return INT_MAX;
if(isminus && ret- 1 > INT_MAX) return INT_MIN;
}
return isminus ? -ret : ret;
}
};