1.字符串全排列
这里仅实现了小写字母,因为逻辑差不多。
采用了两种判断方式,
- 一种是在同一层使用的,为了防止相同值的元素被重复使用造成浪费。
- 另一种是层与层之间,防止相同位置的元素被重复使用造成错误。
所以最外面使用flags数组,长度为字符串的长度;函数内部创建isReapt数组,长度为26。代码如下:
import java.util.ArrayList;
import java.util.List;
public class StringFullPermutation {
boolean[] flags; //表示下标为i的元素是否被访问
List<String> res;
public List<String> permutation(String string){
int length = string.length();
flags = new boolean[length];
for(int i=0;i<length;i++){
flags[i] = false;
}
res = new ArrayList<String>();
findNextChar(string,"");
return res;
}
/**
* 寻找当前字符串的下一个字母
* @param string
* @param now
*/
private void findNextChar(String string, String now) {
int length = string.length();
if(now.length() == length){ //如果长度够了,说明这是一个全排列
res.add(now);
return;
}
int[] isRepeat = new int[26]; //看在这一层是否已经有相同的字母被使用过了,有就不用再使用了(0为未被使用)
for(int i=0;i<length;i++){
if(!flags[i] && isRepeat[string.charAt(i)-'a']==0){ //假如第i个字母未被使用
String newString = now+string.substring(i,i+1);
// System.out.println("now: "+now);
flags[i] = true;
isRepeat[string.charAt(i)-'a'] = 1;
findNextChar(string,newString);
flags[i] = false;
//isReapt只是当前这一层,所以不用回溯
}
}
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
StringFullPermutation s = new StringFullPermutation();
List<String> res= s.permutation("aabc");
for(String ss:res){
System.out.println(ss);
}
}
}
2.螺旋打印数组
这个题起初是我想得简单了,我以为只需要每次对一个元素进行搜索时按照“右下左上”的顺序来就好了。可是后来发现确实不是。
除了按照顺时针方向,同样还需要优先观察与来的方向相同的方向。所以准备如下:
- 一个direct二维数组存储方向
- 一个flags二维数组标志是否被访问
- 递归函数:所需参数 数组、当前元素的行列号、方向
然后按照从来的时候的方向顺时针深度优先遍历即可。
class Solution {
int[][] direct = {{0,1},{1,0},{0,-1},{-1,0}}; //右下左上
int[][] flags; //标志是否被访问,0为未被访问,1为被访问
List<Integer> res;
public List<Integer> spiralOrder(int[][] nums) {
res = new ArrayList<Integer>();
int nr = nums.length;
if(nr==0) return res;
int nc = nums[0].length;
flags = new int[nr][nc];
flags[0][0] = 1;
res.add(nums[0][0]);
findNext(nums,0,0,0);
return res;
}
private void findNext(int[][] nums, int r, int c,int index) {
int i=index; //i表示在direct中的下标
for(int j=0;j<3;j++){
int nr = r + direct[i][0];
int nc = c + direct[i][1];
if(inArea(nums, nr, nc) && flags[nr][nc]==0){
flags[nr][nc] = 1;
res.add(nums[nr][nc]);
findNext(nums, nr, nc,i);
}
i = (i+1)%4;
}
}
private boolean inArea(int[][] nums, int r, int c){
if(r>=0 && c>=0 && r<nums.length && c<nums[0].length){
return true;
}
return false;
}
}