数组求和(练习递归)
方法一:
import java.util.*;
class Main {
static int f(int[] a, int begin, int end) {
if (begin >= end) return 0;
int x = f(a, begin + 1, end);
return x + a[begin];
}
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5};
System.out.println(f(a, 0, a.length));
}
}
方法二:折中求解
class Main {
static int f(int[] a, int begin, int end) {
if (begin == end) {
return a[begin];
} else {
int mid = (begin + end) / 2;
int left = f(a, begin, mid);
int right = f(a, mid + 1, end);
return left + right;
}
}
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5};
System.out.println(f(a, 0, a.length - 1));
}
}
全排列问题
class Solution {
private int len;
private int[] nums;
private boolean[] used;//记录数组的元素有没有被使用
public List<List<Integer>> permute(int[] nums) {
Arrays.sort(nums);//若生成有序集合,注意先排序
this.nums = nums;
this.len = nums.length;
used = new boolean[len];
ArrayList<Integer> row = new ArrayList<>();
return dfs(row);
}
private List<List<Integer>> dfs(ArrayList<Integer> row) {
List<List<Integer>> res = new ArrayList<>();
if (row.size() == len) {
List<Integer> tmp = new ArrayList<>();
for (int e : row)
tmp.add(e);
res.add(tmp);
return res;
}
for (int i = 0; i < nums.length; i++) {
if(!used[i]){
row.add(nums[i]);
used[i] = true;
res.addAll(dfs(row));
row.remove(row.size() - 1);
used[i] = false;//回溯
}
}
return res;
}
public static void main(String[] args) {
int[] nums = {1,3,2};
System.out.println(new Solution().permute(nums));
}
}
全排列的方式不只这一种,但是上面的方法可以得到的全排列是有序的。(参考题目中示例)
全排列 II
分析:
1、在图中 ②
处,搜索的数也和上一次一样,但是上一次的 1
还在使用中;
2、在图中 ①
处,搜索的数也和上一次一样,但是上一次的 1
刚刚被撤销,正是因为刚被撤销,下面的搜索中还会使用到,因此会产生重复,剪掉的就应该是这样的分支。
只要在上面代码的基础上加上这个剪枝条件即可。
for (int i = 0; i < nums.length; i++) {
if(i>0 && nums[i] == nums[i-1] && !used[i-1])
continue;
if(!used[i]){
row.add(nums[i]);
used[i] = true;
res.addAll(dfs(row));
row.remove(row.size() - 1);
used[i] = false;//回溯
}
}
最长公共子序列
import java.util.*;
class Solution{
public int longestCommonSubsequence(String text1, String text2) {
return maxSubqueue(text1,text2);
}
private int maxSubqueue(String s1,String s2){
if(s1==null || s2== null) return 0;
if(s1.length()==0 || s2.length() == 0) return 0;
if(s1.charAt(0) == s2.charAt(0))
return maxSubqueue(s1.substring(1),s2.substring(1)) + 1;
return Math.max(maxSubqueue(s1.substring(1),s2), maxSubqueue(s1,s2.substring(1)));
}
}
单纯的来练习递归,这样提交时会超出时间限制
小白上楼梯问题
class Solution {
public int climbStairs(int n) {
if(n == 1)
return 1;
if(n==2)
return 2;
int res = 0;
res+= climbStairs(n-1) + climbStairs( n - 2);
return res;
}
}
这里依然只是练习,可以考虑改成记忆型递归
或动态规划
寻找旋转排序数组中的最小值
分析: 二分搜索
class Solution {
public int findMin(int[] nums) {
if(nums.length == 1) return nums[0];
int left = 0;
int right = nums.length - 1;
int mid;
while (left != right - 1) {
mid = left + ((right - left) >> 1);
if (nums[left] < nums[mid]) {
if (nums[mid] < nums[right])//说明这时候的子数组有序
return nums[left];
left = mid;
} else {
right = mid;
}
}
return Math.min(nums[left], nums[right]);
}
}
设计一个高效的求解a的n次幂的方法
public static int quickExp(int n,int m) {
int res = 1;
while(m > 0) {
if((m&1)==1) {
res *= n;
}
n = n*n;
m = m>>1;
}
return res;
}
转载:https://blog.csdn.net/idefined/article/details/105876904
查看评论