作为码农,很多人都需要刷题。我在leetcode上面,发现了微软专辑系列。leetcode列出了微软比较常见的面试题,分了八块内容。分别是数组和字符串,链表,树和图,回溯,排序和搜索,动态规划,设计和其他。
今天,说点简单的。说说在数组和字符串里面,微软常见的面试题。leetcode列出了十几道。我抽三道比较简单的leetcode的题目来讲解。
第一道,Reverse String
Write a function that reverses a string. The input string is given as an array of characters char[]
.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
You may assume all the characters consist of printable ascii characters.
Input: ["h","e","l","l","o"]
Output: ["o","l","l","e","h"]
Input: ["H","a","n","n","a","h"]
Output: ["h","a","n","n","a","H"]
其实这道题,如果熟悉python的人,一行就解决了。Reverse String也是微软问的比较多的一道题。
class Solution:
def reverseString(self, s):
s.reverse()
就是简单的把字母逆排序一下。python的reverse()就可以解决了。我记得C++里面也有reverse,有兴趣的可以试试看。
reverse(str.begin(),str.end());
当然,也可以用java和C++。用递归也可以解决。设置,左右两个指针,然后交换指针即可。但是要注意,更换以后,原字符串的大小也要发生变化,左边需要加以,右边需要减一。来适应更改后的长度。
首先写出递归方程。
Base Condition: left > right, 即不存在。
If left <= right, 交换左右,并且更改长度。
看代码:
class Solution {
public void helper(char[] s, int left, int right) {
if (left >= right) return;
char tmp = s[left];
s[left++] = s[right];
s[right--] = tmp;
helper(s, left, right);
}
public void reverseString(char[] s) {
helper(s, 0, s.length - 1);
}
}
其实用完递归以后,我将觉得差不多好像就可以了。但是leetcode给了一个更炫酷的解法。请看下图:
这个方法,更快,而且更加的容易理解整个过程!每次只需要对首尾两个进行交换,然后交换即可。每次左边再自增加一,右边减一。慢慢的检索到中间!So Smart!
class Solution {
public void reverseString(char[] s) {
int left = 0, right = s.length - 1;
while (left < right) {
char tmp = s[left];
s[left++] = s[right];
s[right--] = tmp;
}
}
}
第二道:Reverse Words in a String.
Given an input string, reverse the string word by word.
Example:
Input: "the sky is blue"
output: "blue is sky the"
Input: "a good example"
Output: "example good a"
Explanation: You need to reduce multiple spaces between two words to a single space in the reversed string.
Input: " hello world! "
Output: "world! hello"
Explanation: Your reversed string should not contain leading or trailing spaces.
这道题,我一开始没有意识到复杂程度。我记得阿里巴巴也喜欢问这种类似的逆序句子。我一开始提交的代码是:
class Solution {
public String reverseWords(String s) {
stringstream ss(s);
string res="",tmp;
while(s>tmp){
if(res =="")
res = tmp;
else
res = tmp + " " + res;
}
cout<<res<<endl;
}
}
该解法,很有效也很简单。我用stringstream进行分割语句,然后把它存在一个res里面,然后每次倒序相加。最后输出该语句,完成逆序。
第二种思路就是把整个句子进行看作整体,进行反转。然后反转每个单词,反转完以后,把多余的空格删除。注意,在反转完整体以后,还要把前后的空格也删掉。
class Solution {
public:
string reverseWords(string s) {
// reverse the whole string
reverse(s.begin(), s.end());
int n = s.size();
int idx = 0;
for (int start = 0; start < n; ++start) {
if (s[start] != ' ') {
// go to the beginning of the word
if (idx != 0) s[idx++] = ' ';
// go to the end of the word
int end = start;
while (end < n && s[end] != ' ') s[idx++] = s[end++];
// reverse the word
reverse(s.begin() + idx - (end - start), s.begin() + idx);
// move to the next word
start = end;
}
}
s.erase(s.begin() + idx, s.end());
return s;
}
}
第三种,我觉得可以用到C++和Java里面的reverse。当我把单个单词切割出来以后,我把它存在一个数组里面,然后逆序输出这样数组就好了。但要注意删除首尾的额外空间。
class Solution {
public String reverseWords(String s) {
// remove leading spaces
s = s.trim();
// split by multiple spaces
List<String> wordList = Arrays.asList(s.split("s+"));
Collections.reverse(wordList);
return String.join(" ", wordList);
}
}
第三道:Sprial Matrix
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
Example:
Input:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
Output: [1,2,3,6,9,8,7,4,5]
Input:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]
这一道其实就是矩阵变换的题目。Java里面的有矩阵可以用。想要把数字按照逆时针输出,我觉得只要把握好相应的行列,即可。
因为是逆时针的一个圈,所以我们可以把这些数字放在一个新的数组里面,然后存放在里面即可。
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List ans = new ArrayList();
if (matrix.length == 0) return ans;
int R = matrix.length, C = matrix[0].length;
boolean[][] seen = new boolean[R][C];
int[] dr = {0, 1, 0, -1};
int[] dc = {1, 0, -1, 0};
int r = 0, c = 0, di = 0;
for (int i = 0; i < R * C; i++) {
ans.add(matrix[r][c]);
seen[r][c] = true;
int cr = r + dr[di];
int cc = c + dc[di];
if (0 <= cr && cr < R && 0 <= cc && cc < C && !seen[cr][cc]){
r = cr;
c = cc;
} else {
di = (di + 1) % 4;
r += dr[di];
c += dc[di];
}
}
return ans;
}
}
leetcode上面给了一个更加炫酷的方法。
按照这样的方法,然后依次输出每行的结果,按照上,右,下,左进行按次序输出每行的数字。重新组成一个矩阵。
简直太智慧了!
class Solution {
public List < Integer > spiralOrder(int[][] matrix) {
List ans = new ArrayList();
if (matrix.length == 0)
return ans;
int r1 = 0, r2 = matrix.length - 1;
int c1 = 0, c2 = matrix[0].length - 1;
while (r1 <= r2 && c1 <= c2) {
for (int c = c1; c <= c2; c++) ans.add(matrix[r1][c]);
for (int r = r1 + 1; r <= r2; r++) ans.add(matrix[r][c2]);
if (r1 < r2 && c1 < c2) {
for (int c = c2 - 1; c > c1; c--) ans.add(matrix[r2][c]);
for (int r = r2; r > r1; r--) ans.add(matrix[r][c1]);
}
r1++;
r2--;
c1++;
c2--;
}
return ans;
}
}
以上,就是这三道例题。如有问题,请随时告知我。我将立刻更改。能力赢弱,欢迎指正。
Andrew Ni
可以关注我的公众号联系我。