一.爬楼梯问题
假设你正在爬楼梯。需要 n
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
思考:看似比较复杂其实多往下写上几层就会发现其中的规律,往往后一层的方法为前两层方法之合,由此可以得出公式F(n)=F(n-1)+F(n-2),这个公式看上去与Fibonacci数列有些相似,但是初始数列为1,2后面满足改公式
解法一:使用数组首先把一二层数据保存,将所需楼层的层数通过形参传递到方法,再通过开辟一个新数组大小为楼层数n,再依次算出n层的方法。(需要开辟新空间)
int[] arr = new int[n];
arr[0]=1;
arr[1]=2;
for (int i = 2; i < arr.length; i++) {
arr[i]=arr[i-1]+arr[i-2];
}
return arr[arr.length-1];
解法二:使用两个变量保存之前楼层的方法,prePre保存n-2时的方法数,pre保存n-1时的方法数,r保存当前楼层的方法数。
if (n==1) return 1;
if (n==2) return 2;
int pre = 1, prePre = 2, r = 0;
for (int i = 3; i <= n; ++i) {
r=pre+prePre;
pre=r;
prePre=pre;
}
return r;
解法三:使用递归,将每层所需要的方法数当参数传递。
优化使用HashMap保存已经计算过楼层的方法数直接返回
// if (n==1) return 1;
// if (n==2) return 2;
//
// int res=climbNum(n-1)+climbNum(n-2);
//
// return res;
//优化后
HashMap<Integer, Integer> map = new HashMap<>();
if (n==1) return 1;
if (n==2) return 2;
if (null!=map.get(n)){
return map.get(n);
}else {
int res=climbNum(n-1)+climbNum(n-2);
map.put(n,res);
return res;
}
二.买卖股票的最佳时机
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
思考:用每个数字都遍历一遍数组,保存那个与后面的数字相减的到最大的数字,此数字就为最大利润
解法一:双层for遍历数组
int maProfit = 0;
for (int i = 0; i < prices.length; i++) {
for (int j = i + 1; j < prices.length; j++) {
int profit=prices[j] - prices[i];
if (maProfit < profit) {
maProfit=profit;
}
}
}
return maProfit;
解法二:
int minprice = Integer.MAX_VALUE;
int maxprofit = 0;
for (int i = 0; i < prices.length; i++) {
if (prices[i] < minprice) {
minprice = prices[i];
} else if (prices[i] - minprice > maxprofit) {
maxprofit = prices[i] - minprice;
}
}
return maxprofit;
三.只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
解法一:当出现相同key值时删除此值,则最后保留在HashMap中的就是只出现过一次的数字
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
if (map.containsKey(arr[i])){
map.remove(arr[i]);
}else {
map.put(arr[i], 0);
}
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey());
}
解法二:通过异或运算相同为0,遍历数组后最后那个数字为只出现一次的数
public static int method2(int [] nums){
int num=0;
for (int i : nums) {
num^=i;
}
return num;
}
四.两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
思考:遍历数组寻找其中那两个数字
解法一:双层for循环遍历将可得到target的下标传递
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
arr[0] = i;
arr[1] = j;
System.out.println(Arrays.toString(arr));
}
}
}
解法二:使用HashMap用target将每个数字减掉的数在数组中比对,如果可以找到那就是这两个数字(利用空间换时间)
Map<Integer, Integer> hashtable = new HashMap<>();
for (int i = 0; i < nums.length; ++i) {
if (hashtable.containsKey(target - nums[i])) {
return new int[]{hashtable.get(target - nums[i]), i};
}
hashtable.put(nums[i], i);
}
return new int[0];