BFS和DFS
public void dfs(boolean[][] grid,boolean[][] vis,int i,int j){
// vis的访问放在最后面
if(i<0||i>=grid.length||j<0||j>=grid[0].length) return;
if(grid[i][j]==true&&vis[i][j]==false){
vis[i][j]=true;
dfs(grid,vis,i-1,j);
dfs(grid,vis,i+1,j);
dfs(grid,vis,i,j-1);
dfs(grid,vis,i,j+1);
}
else return;
}
public void bfs(boolean[][] grid,boolean[][] vis,int i,int j){
Vector<Point> record=new Vector<>();
int[] delta_x=new int[]{-1,1,0,0};
int[] delta_y=new int[]{0,0,-1,1};
record.add(new Point(i, j));
while(record.size()>0){
Point p=record.remove(0);
vis[p.x][p.y]=true;
for(int index=0;index<4;index++){
int new_x=p.x+delta_x[index];
int new_y=p.y+delta_y[index];
if(new_x>=0&&new_x<grid.length&&new_y>=0&&new_y<grid[0].length&&vis[new_x][new_y]==false&&grid[new_x][new_y]==true){
record.add(new Point(new_x,new_y));
}
}
}
}
public int numIslands(boolean[][] grid) {
// Write your code here
boolean[][] vis=new boolean[grid.length][grid[0].length];
int cnt=0;
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[0].length;j++){
if(grid[i][j]==true&&vis[i][j]==false){
cnt++;
// dfs(grid,vis,i,j);
bfs(grid,vis,i,j);
}
}
}
return cnt;
}
BFS
题目地址:http://www.lintcode.com/problem/binary-tree-level-order-traversal/
public List<List<Integer>> levelOrder(TreeNode root) {
// write your code here
List result = new ArrayList();
if(root== null)
return result;
Queue<TreeNode> queue = new LinkedList<TreeNode>();//linkedlist 是queue的子类
queue.add(root);
while(!queue.isEmpty()){
ArrayList<Integer>level = new ArrayList<Integer>();
int size = queue.size();
for(int i=0; i< size;i++){
TreeNode head = queue.poll();
level.add(head.val);
if(head.left!=null){
queue.offer(head.left);
}
if (head.right!=null){
queue.offer(head.right);
}
}
result.add(level);
}
return result;
}
了解一下递归的写法
问题描述:求解Fibonacci数列的第n个位置的值?指的是这样一个数列:1、1、2、3、5、8、13、21、……
解法1:传统的递归做法,当n比较大的时候比较费时间
public int fib(int index){
if(index==1||index==2){
return 1;
}else{
return fib(index-1)+fib(index-2);
}
}
解法2:在传统的做法上加上了一个记录数组,节省了一定时间
public int fibona(int index,int[] nums){
if(nums[index]!=0) return nums[index];
if(index==1||index==2){
nums[index]=1;
return 1;
}else{
nums[index]=fib(index-1)+fib(index-2)
return nums[index];
}
}
解法3:相当与动态规划的做法,从边界向目标一边记录一边遍历。
public int fibonacci(int index){
int a=1,b=1,result=0;
for(int i=0;i<=index;i++){
if(i<=2) result=a;
else{
result=a+b;
a=b;
b=result;
}
}
return result;
}
对于回溯问题(递归)的通用解法
这个解法可以应用于很多回溯问题,比如Subsets, Permutations, and Combination Sum。
Subsets : https://leetcode.com/problems/subsets/
解法1:把问题分成很多子问题。(推荐这种,因为方便处理后面的subsets II )
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, 0);
return list;
}
private void backtrack(List<List<Integer>> list , List<Integer> tempList, int [] nums, int start){
list.add(new ArrayList<>(tempList));
for(int i = start; i < nums.length; i++){
tempList.add(nums[i]);
backtrack(list, tempList, nums, i + 1);
tempList.remove(tempList.size() - 1);
}
}
解法2:对于每个数都有放入和不放入两种状态,从左到右遍历数组,枚举每种状态。
public void backstrack2(List<List<Integer>> list,List<Integer> temp,int index,int[] nums){
if(index==nums.length){
list.add(new ArrayList<>(temp));
return;
}else{
temp.add(nums[index]);
backstrack2(list, temp, index+1, nums);
temp.remove(temp.size()-1);
backstrack2(list, temp, index+1, nums);
}
}
public List<List<Integer>> subsets(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> list=new ArrayList<>();
backstrack2(list, new ArrayList<>(), 0, nums);
return list;
}
Subsets II (contains duplicates) : https://leetcode.com/problems/subsets-ii/
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, int start){
list.add(new ArrayList<>(tempList));
for(int i = start; i < nums.length; i++){
if(i > start && nums[i] == nums[i-1]) continue; // skip duplicates
tempList.add(nums[i]);
backtrack(list, tempList, nums, i + 1);
tempList.remove(tempList.size() - 1);
}
}
Permutations : https://leetcode.com/problems/permutations/
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
// Arrays.sort(nums); // not necessary
backtrack(list, new ArrayList<>(), nums);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
if(tempList.size() == nums.length){
list.add(new ArrayList<>(tempList));
} else{
for(int i = 0; i < nums.length; i++){
if(tempList.contains(nums[i])) continue; // element already exists, skip
tempList.add(nums[i]);
backtrack(list, tempList, nums);
tempList.remove(tempList.size() - 1);
}
}
}
Permutations II (contains duplicates) : https://leetcode.com/problems/permutations-ii/
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);//不能忘记这步
backtrack(list, new ArrayList<>(), nums, new boolean[nums.length]);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, boolean [] used){
if(tempList.size() == nums.length){
list.add(new ArrayList<>(tempList));
} else{
for(int i = 0; i < nums.length; i++){
//如果这个位置已经被访问过
//两个位置的数如果是一样的,那么只有前面的数用过之后,采用现在这个数,这样就保证了2,2,只有有一种组合
if(used[i] || i > 0 && nums[i] == nums[i-1] && !used[i - 1]) continue;
used[i] = true;
tempList.add(nums[i]);
backtrack(list, tempList, nums, used);
//回溯回来要修改两个地方
used[i] = false;
tempList.remove(tempList.size() - 1);
}
}
}
Combination Sum : https://leetcode.com/problems/combination-sum/
public List<List<Integer>> combinationSum(int[] nums, int target) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, target, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, int remain, int start){
if(remain < 0) return;
else if(remain == 0) list.add(new ArrayList<>(tempList));
else{
for(int i = start; i < nums.length; i++){
tempList.add(nums[i]);
backtrack(list, tempList, nums, remain - nums[i], i); // not i + 1 because we can reuse same elements
tempList.remove(tempList.size() - 1);
}
}
}
Combination Sum II (can’t reuse same element) : https://leetcode.com/problems/combination-sum-ii/
public List<List<Integer>> combinationSum2(int[] nums, int target) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, target, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, int remain, int start){
if(remain < 0) return;
else if(remain == 0) list.add(new ArrayList<>(tempList));
else{
for(int i = start; i < nums.length; i++){
if(i > start && nums[i] == nums[i-1]) continue; // skip duplicates
tempList.add(nums[i]);
backtrack(list, tempList, nums, remain - nums[i], i + 1);
tempList.remove(tempList.size() - 1);
}
}
}
Palindrome Partitioning : https://leetcode.com/problems/palindrome-partitioning/
public List<List<String>> partition(String s) {
List<List<String>> list = new ArrayList<>();
backtrack(list, new ArrayList<>(), s, 0);
return list;
}
public void backtrack(List<List<String>> list, List<String> tempList, String s, int start){
if(start == s.length())
list.add(new ArrayList<>(tempList));
else{
for(int i = start; i < s.length(); i++){
if(isPalindrome(s, start, i)){
tempList.add(s.substring(start, i + 1));
backtrack(list, tempList, s, i + 1);
tempList.remove(tempList.size() - 1);
}
}
}
}
public boolean isPalindrome(String s, int low, int high){
while(low < high)
if(s.charAt(low++) != s.charAt(high--)) return false;
return true;
}
链表
Reverse Linked List
https://leetcode.com/problems/reverse-linked-list/description/
Your solution
public ListNode reverseList(ListNode head) {
// write your code here
ListNode prev =null;
while(head!=null){
ListNode temp= head.next;
head.next = prev;
prev =head;
head=temp;
}
return prev;
}
My solution
public ListNode reverseList(ListNode head) {
ListNode dummy=new ListNode(0);
dummy.next=head;
ListNode tail=dummy,next=head;
ListNode flag=dummy;
ListNode temp=null;
while(next!=null){
temp=next.next;//assign new next in temp
if(tail.next==next) {
flag=next;
next=temp;
continue;
}
next.next=tail.next;
tail.next=next;//insert
next=temp;// update next
}
flag.next=temp;
return dummy.next;
}
Reverse Linked List II
https://leetcode.com/problems/reverse-linked-list-ii/description/
public ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dummy=new ListNode(0);
dummy.next=head;
ListNode tail=dummy;
while(m>1){
m--;
n--;
tail=tail.next;
}
ListNode next=tail.next;
ListNode flag=tail.next;
ListNode temp=null;
while(n>0){
n--;
temp=next.next;//store next new node
if(tail.next==next) {
flag=next;//store the final tail node
next=temp;
continue;
}
next.next=tail.next;
tail.next=next;
next=temp;
}
flag.next=temp;
return dummy.next;
}
Reverse Nodes in k-Groups
https://leetcode.com/problems/reverse-nodes-in-k-group/description/
对每k个都标记好head和tail,然后把head后面的元素,一个一个拿下来放到传入到tail的后面
public ListNode reverseKGroup(ListNode head, int k) {
if(head==null||head.next==null||k<2) return head;
ListNode dummy=new ListNode(0);
dummy.next=head;
ListNode prev=dummy,tail=dummy;
while(true){
int cnt=k;
while(cnt!=0&&tail!=null){
tail=tail.next;
cnt--;
}
if(tail==null) break;
head=prev.next;
while(prev.next!=tail){
ListNode temp=prev.next;//Assign
prev.next=temp.next;//Delete
temp.next=tail.next;
tail.next=temp;//Insert
}
prev=head;
tail=head;
}
return dummy.next;
}
排序
对于链表的排序
http://www.lintcode.com/en/problem/sort-list/
解法1:快速排序
public ListNode part(ListNode head,ListNode tail){
int key=head.val;
ListNode slow=head,fast=head.next;
while(fast!=tail){
if(fast.val<key){
slow=slow.next;
int temp=fast.val;
fast.val=slow.val;
slow.val=temp;
}
fast=fast.next;
}
int temp=head.val;
head.val=slow.val;
slow.val=temp;
return slow;
}
public void quick(ListNode head,ListNode tail){
if(head==tail) return;
ListNode pivot=part(head, tail);
quick(head, pivot);
quick(pivot.next, tail);
}
public ListNode sortList(ListNode head) {
// write your code here
quick(head, null);
return head;
}
解法2:归并排序
public ListNode sortList(ListNode head){
if(head==null||head.next==null) return head;
ListNode head1=getMid(head);
head=sortList(head);
head1=sortList(head1);
return merge(head,head1);
}
public ListNode getMid(ListNode head){
ListNode fast=head.next,slow=head.next,prev=head;
while(fast!=null){
if(fast==null) break;
fast=fast.next;
if(fast==null) break;
fast=fast.next;
prev=slow;
slow=slow.next;
}
prev.next=null;//this is very important
return slow;
}
public ListNode merge(ListNode head1,ListNode head2){
ListNode newNode= new ListNode(-1);
ListNode tail=newNode;
while(head1!=null&&head2!=null){
if(head1.val<=head2.val){
tail.next=head1;
head1=head1.next;
}else{
tail.next=head2;
head2=head2.next;
}
tail=tail.next;
tail.next=null;//this is very important
}
if(head1!=null) tail.next=head1;
if(head2!=null) tail.next=head2;
return newNode.next;
}