题目:
我的思路:
按照这个思路实现的代码如下:
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
if(matrix == null) {
return new ArrayList<Integer>();
}
if(matrix.length == 0) {
return new ArrayList<Integer>();
}
List<Integer> rslt = new ArrayList<Integer>();
//1、定义4个变量分别表示横向最大、最小和纵向最大最小
int colFirst = 0, rowFirst = 0;
int colLast = matrix[0].length - 1, rowLast = matrix.length - 1;
int num = matrix[0].length * matrix.length;
//2、遍历的索引
int i = 0, j = 0;
//3、四个布尔值变量用来判断进入哪一个if判断
boolean colToBig = true, rowToBig = false, colToSmall = false, rowToSmall = false;
for(int a = 0; a < num; a++) {
if(i <= colLast && colToBig) {
rslt.add(matrix[j][i]);
if(i < colLast) {
//4、j保持不变,i加1,这样从左往右遍历
i++;
} else {
//5、遍历到最后一个值的时候,纵向最小值加1,j加1,i保持不变,用于下次遍历
rowFirst++;
j++;
//6、重置布尔值,用于下次判断
colToBig = false;
rowToBig = true;
continue;
}
}
if(j <= rowLast && rowToBig) {
rslt.add(matrix[j][i]);
if(j < rowLast) {
j++;
} else {
colLast--;
i--;
rowToBig = false;
colToSmall = true;
continue;
}
}
if(i >= colFirst && colToSmall) {
rslt.add(matrix[j][i]);
if(i > colFirst) {
i--;
} else {
rowLast--;
j--;
colToSmall = false;
rowToSmall = true;
continue;
}
}
if(j >= rowFirst && rowToSmall) {
rslt.add(matrix[j][i]);
if(j > rowFirst && rowToSmall) {
j--;
} else {
colFirst++;
i++;
rowToSmall = false;
colToBig = true;
}
}
}
return rslt;
}
}
反思:
在代码中我还定义了四个布尔值变量:
boolean colToBig = true, rowToBig = false, colToSmall = false, rowToSmall = false;
这是用来控制是否进入判断逻辑的,因为在刚开始我没有定义这四个变量的时候,在for循环中,i和j很可能满足多个if判断逻辑,但是实际上我们只希望每次遍历的时候只走进其中一个if判断,因此定义布尔值变量,并在每次遍历到最后的时候进行重置,这样就能保证每次只进入一个if判断了。
题目:
我的思路:
按照这个思路实现的代码如下:
class Solution {
public List<List<Integer>> generate(int numRows) {
if(numRows == 0) {
return new ArrayList<List<Integer>>();
}
List<List<Integer>> rslt = new ArrayList<List<Integer>>();
List<Integer> row;
for(int i = 0; i < numRows; i++) {
row = new ArrayList<Integer>();
if(i == 0) {
//1、第1行直接赋值
row.add(1);
rslt.add(row);
} else {
for(int j = 0; j <= i; j++) {
//2、第i行就有i个数
if(j - 1 < 0) {
//3、最左边的数
row.add(0 + rslt.get(i - 1).get(j));
} else if(j >= rslt.get(i - 1).size()) {
//4、最右边的数
row.add(rslt.get(i - 1).get(j - 1) + 0);
} else {
//5、其余的数只需要左上方的数和右上方的数相加即可
row.add(rslt.get(i - 1).get(j - 1) + rslt.get(i - 1).get(j));
}
}
rslt.add(row);
}
}
return rslt;
}
}
题目:
我的思路:
这一题我的思路和第一篇中介绍的题目《加一》类似,将两个字符串分别转换为字符数组,然后将每一位分别相加,得到结果,如果遇到进位的情况,需要再原有结果上再加1,我们首先来看实现。
按照这个思路实现的代码如下:
class Solution {
public String addBinary(String a, String b) {
//1、将字符串转换为字符数组,并比较得到长度长的数组和短的数组
char[] aChars = a.toCharArray();
char[] bChars = b.toCharArray();
char[] longChars;
char[] minChars;
int aLen = aChars.length, bLen = bChars.length, minLen, maxLen;
if(aLen <= bLen) {
minLen = aLen;
maxLen = bLen;
minChars = aChars;
longChars = bChars;
} else {
minLen = bLen;
maxLen = aLen;
minChars = bChars;
longChars = aChars;
}
StringBuffer sb = new StringBuffer();
//2、定义一个布尔值用于控制是否进位
boolean fwdPlus = false;
int i = minLen - 1, j = maxLen - 1;
for(int k = 0; k < maxLen; k++) {
//3、以长度较长的数组为基准,分别遍历两个数组,如果长度短的数组还未遍历结束,
//则将长数组和短数组对应位置的数相加
if(j >= maxLen - minLen) {
if(minChars[i] == '0' && longChars[j] == '0') {
if(fwdPlus) {
sb.insert(0, 1);
fwdPlus = false;
} else {
sb.insert(0, 0);
fwdPlus = false;
}
} else if(minChars[i] == '0' && longChars[j] == '1') {
if(fwdPlus) {
sb.insert(0, 0);
fwdPlus = true;
} else {
sb.insert(0, 1);
fwdPlus = false;
}
} else if(minChars[i] == '1' && longChars[j] == '0') {
if(fwdPlus) {
sb.insert(0, 0);
fwdPlus = true;
} else {
sb.insert(0, 1);
fwdPlus = false;
}
} else if(minChars[i] == '1' && longChars[j] == '1') {
if(fwdPlus) {
sb.insert(0, 1);
fwdPlus = true;
} else {
sb.insert(0, 0);
fwdPlus = true;
}
}
j--;
i--;
} else {
//4、短数组遍历结束,则直接遍历长数组剩余的位数,并根据是否进位来获得结果
if(longChars[j] == '0') {
if(fwdPlus) {
sb.insert(0, 1);
fwdPlus = false;
} else {
sb.insert(0, 0);
fwdPlus = false;
}
} else if(longChars[j] == '1') {
if(fwdPlus) {
sb.insert(0, 0);
fwdPlus = true;
} else {
sb.insert(0, 1);
fwdPlus = false;
}
}
j--;
}
}
//5、长短数组全部遍历结束,如果仍需进位,则在最前面加1
if(fwdPlus) {
sb.insert(0, 1);
}
return sb.toString();
}
}
反思:
题目:
我的思路:
看到这一题第一个想法就是直接调用Java中String类的indexOf()方法,一句话就可以完成,也符合题目的要求:
class Solution {
public int strStr(String haystack, String needle) {
return haystack.indexOf(needle);
}
}
但是如果不使用Java原生的方法的话,那该怎么做呢?我认为可以从第0位开始遍历字符串,每次从haystack中获取needle长度的字符串,判断这个字符串是否和needle长度相同,如果不同则遍历的索引向后移动一位,如果相同则得到结果。
按照这个思路实现的代码如下:
class Solution {
public int strStr(String haystack, String needle) {
if(haystack == null || "".equals(needle)) {
return 0;
}
int len = needle.length(), index = -1;
//1、i只需要遍历到haystack.length()-neddle.length()即可,防止出现数组越界
for(int i = 0; i + len <= haystack.length(); i++) {
if(needle.equals(haystack.substring(i, i + len))) {
index = i;
break;
}
}
return index;
}
}
题目:
我的思路:
这一题我的思路比较直接,我以字符串数组的第一个字符串为基准,从第1位开始依次截取字符串获得前缀,每截取一次则将前缀与其余的字符串进行比较,如果其余的字符串均是以此为前缀,则继续截取更大的前缀,否则得到结果。
按照这个思路实现的代码如下:
class Solution {
public String longestCommonPrefix(String[] strs) {
String rslt = "", prefix = "";
if(strs.length > 0) {
for(int i = 1; i <= strs[0].length(); i++) {
//1、获得第一个字符串的前缀
prefix = strs[0].substring(0, i);
if(strs.length > 1) {
for(int j = 1; j < strs.length; j++) {
if(!strs[j].startsWith(prefix)) {
//2、如果某个字符串不是以此为前缀,则得到最长公共前缀
break;
} else {
//3、字符串以此为前缀,并且已经遍历到字符串数组的最后,
//则可以继续判断,获取更大的公共前缀
if(j == strs.length - 1) {
rslt = prefix;
}
}
}
} else {
rslt = prefix;
}
}
}
return rslt;
}
}
题目:
我的思路:
这一题比较简单,有很多种方法可以解决,我当时做的时候采用的是一个比较耗时的方法,就是从最后依次向前遍历整个字符串,从而得到结果。
按照这个思路实现的代码如下:
class Solution {
public String reverseString(String s) {
if(s == null) {
return null;
}
if("".equals(s)) {
return "";
}
char[] c = s.toCharArray();
StringBuffer sb = new StringBuffer();
for(int i = c.length - 1; i >= 0; i--) {
sb.append(c[i]);
}
return sb.toString();
}
}
反思:
这道题实际上还有一个比较高效的解法,就是使用双指针,可以定义两个指针指向字符串的最小索引和最大索引,然后交换两个指针指向的值,再依次后移最小索引、前移最大索引,直到两个指针相遇。基于此想法我又修改了我的代码:
class Solution {
public String reverseString(String s) {
if(s == null || "".equals(s)) {
return s;
}
char[] sChars = s.toCharArray();
for(int i = 0, j = sChars.length - 1; i < j; i++, j--) {
char tmp = sChars[i];
sChars[i] = sChars[j];
sChars[j] = tmp;
}
return new String(sChars);
}
}