1、二维数组中的查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]给定 target = 7,返回 true。给定 target = 3,返回 false。
解法一
- 每一行记录都是一个一维有序数组,可以用二分查找
public class Solution {public boolean Find(int target, int [][] array) {for(int i=0;i<array.length;i++){int low=0;int high=array[i].length-1;while(low <= high){int mid = (low+high)/2;if(target > array[i][mid])low=mid+1;else if(target < array[i][mid])high=mid-1;elsereturn true;}}return false;}}
- 每一行记录都是一个一维有序数组,可以用二分查找
解法二
- 利用此二维数组的性质,从上到下递增,从左到右递增
- 那么从左下或者右上作为起点
- 小于左下就i—,大于左下就j++s
- 或者 小于右上就j—,大于右上就i++
public class Solution {public boolean Find(int target, int [][] array) {int row=array.length-1;int col=0;while(row>=0 && col<array[0].length){if(array[row][col] == target){return true;}else if(array[row][col] > target){row--;}else{col++;}}return false;}}
2、替换空格
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
方法一
- 利用Java中String 类的方法 String replace(CharSequence old, CharSequence new) ```java import java.util.*;
public class Solution { /**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param s string字符串* @return string字符串*/public String replaceSpace (String s) {// write code herereturn s.replace(" ","%20");}
}
- 方法二- 利用StringBuilder不用重新建立字符串,更快速,效率高```javaimport java.util.*;public class Solution {public String replaceSpace (String s) {// write code hereStringBuilder sb = new StringBuilder();for(char c : s.toCharArray()){sb.append(c==' '?"%20":c);}return sb.toString();}}
3、从尾到头打印链表
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
- 解法一
- 建立一个辅助数组arr来将链表值进行反转即可 ```java /**
- public class ListNode {
- int val;
- ListNode next = null; *
- ListNode(int val) {
- this.val = val;
- }
- }
*/
import java.util.ArrayList;
public class Solution {
public ArrayList
printListFromTailToHead(ListNode listNode) { int len = 0; ListNode p = listNode; while(p != null){
} int arr[] =new int[len]; p = listNode; int t = len-1; while(p != null){len++;p = p.next;
} ArrayListarr[t] = p.val;t--;p = p.next;
list = new ArrayList(len); for(int i=0;i<len;i++){
} return list; } } ```list.add(arr[i]);
- 解法二
- 利用递归,先往链表后面走,再add到ArrayList中 ```java /**
- public class ListNode {
- int val;
- ListNode next = null; *
- ListNode(int val) {
- this.val = val;
- }
} / import java.util.ArrayList; public class Solution { ArrayList
list = new ArrayList (); public ArrayList printListFromTailToHead(ListNode listNode) { if(listNode != null){ this.printListFromTailToHead(listNode.next);list.add(listNode.val);
} return list; } }
<a name="Lkb5N"></a># 4、重建二叉树```java输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
/*** Definition for binary tree* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val = x; }* }*/public class Solution {public TreeNode reConstructBinaryTree(int [] pre,int [] in) {TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);return root;}//前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {if(startPre>endPre||startIn>endIn)return null;TreeNode root=new TreeNode(pre[startPre]);for(int i=startIn;i<=endIn;i++)if(in[i]==pre[startPre]){root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);break;}return root;}}
5、用两个栈实现一个队列
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型
- 方法
- Push操作,当栈1还没满时,则往栈1添加push;当栈1满了时,则将栈1全部数据往栈2移动,再push数据到栈1
- Pop操作,当栈2不为空,则pop栈2数据;栈2为空,则将栈1全部数据移动到栈2再pop栈2数据 ```java import java.util.Stack;
public class Solution {
Stack
public int pop() {//如果栈2有,就从栈2取if(!stack2.isEmpty()){return stack2.pop();}//否则将栈1所有元素往栈2里面移动,再取数据while(!stack1.isEmpty()){int sum = stack1.pop();stack2.push(sum);}return stack2.pop();}
}
- 如果是两个队列,那么如何实现一个栈- 入栈直接让元素入队列1- 出栈,假如队列1只剩一个元素,就让它出队(出栈);否则,将队列1的其它元素出队 并 入队到队列2,将队列1的唯一元素出队(出栈),最后队列2的全部元素出对列 并入队列到队列1<a name="QCx2B"></a># 6、旋转数组的最小数字```java把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
解法一
- 从后面往前面遍历,找到 由小变大 的那个变化,小的值即为所求
import java.util.ArrayList;public class Solution {public int minNumberInRotateArray(int [] array) {if(array.length == 0){return 0;}int j = array.length-1;int i = j-1;int sum = array[j];while(j>0){if(array[i]>array[j]){break;}if(sum > array[j]){sum = array[j];}if(sum > array[i]){sum = array[i];}j--;i = j-1;}return sum;}}
- 从后面往前面遍历,找到 由小变大 的那个变化,小的值即为所求
解法二
- 二分查找法
mid = low + (high - low)/2需要考虑三种情况:(1)array[mid] > array[high]:出现这种情况的array类似[3,4,5,6,0,1,2],此时最小数字一定在mid的右边。low = mid + 1(2)array[mid] == array[high]:出现这种情况的array类似 [1,0,1,1,1] 或者[1,1,1,0,1],此时最小数字不好判断在mid左边还是右边,这时只好一个一个试 ,high = high - 1(3)array[mid] < array[high]:出现这种情况的array类似[2,2,3,4,5,6,6],此时最小数字一定就是array[mid]或者在mid的左边。因为右边必然都是递增的。high = mid注意这里有个坑:如果待查询的范围最后只剩两个数,那么mid 一定会指向下标靠前的数字比如 array = [4,6]array[low] = 4 ;array[mid] = 4 ; array[high] = 6 ;如果high = mid - 1,就会产生错误, 因此high = mid但情形(1)中low = mid + 1就不会错误
public class Solution {public int minNumberInRotateArray(int [] array) {int low = 0 ; int high = array.length - 1;while(low < high){int mid = low + (high - low) / 2;if(array[mid] > array[high]){low = mid + 1;}else if(array[mid] == array[high]){high = high - 1;}else{high = mid;}}return array[low];}}
7、波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。其中n≤39
- 二分查找法
斐波那契数列第0项为0,第一项为1,后面数的都是等于它前两项之和
方法一
- 利用递归,占用内存大,耗时长,容易栈溢出
public class Solution {public int Fibonacci(int n) {if(n<=1){return n;}return Fibonacci(n-1)+Fibonacci(n-2);}}
- 利用递归,占用内存大,耗时长,容易栈溢出
方法二
- 利用辅助数组,长度为n+1(斐波那契数列从0开始,有n+1项),来存每个数据
public class Solution {public int Fibonacci(int n){if(n<=1){return n;}int[] arr = new int[n+1];arr[0] = 0;arr[1] = 1;for(int i = 2;i<n+1;i++){arr[i] = arr[i-1] + arr[i-2];}return arr[n];}}
8、跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)
- 利用辅助数组,长度为n+1(斐波那契数列从0开始,有n+1项),来存每个数据
解法一
- 可以通过找规律的办法:n=1 时,1种;n=2 时,2种;n=3 时,3种;n=4 时,5种;n=5 时,8种……
- 得出f(n) = f(n-1) + f(n-2),初始条件:n=1,1种;n=2,2种
- 也可以这么想: ```java a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);
- 可以通过找规律的办法:n=1 时,1种;n=2 时,2种;n=3 时,3种;n=4 时,5种;n=5 时,8种……
b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)
c.由a、b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)
d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2
e.可以发现最终得出的是一个斐波那契数列:
| 1, (n=1)
f(n) = | 2, (n=2)
| f(n-1)+f(n-2) ,(n>2,n为整数)
```javapublic class Solution {public int jumpFloor(int target) {if(target == 1){return 1;}if(target == 2){return 2;}return jumpFloor(target-1)+jumpFloor(target-2);}}
解法二
- 利用辅助数组
public class Solution {public int jumpFloor(int target) {if(target == 1){return 1;}if(target == 2){return 2;}int[] temp = new int[target];temp[0] = 1;temp[1] = 2;for(int i=2;i<target;i++){temp[i] = temp[i-1] + temp[i-2];}return temp[target-1];}}
9、变态跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级求该青蛙跳上一个n级的台阶总共有多少种跳法
- 利用辅助数组
解法
关于本地:前提是n个台阶会有一次n阶的跳法,分析:f(1) = 1f(2) = f(2-1)+f(2-2)f(3) = f(3-1)+f(3-2)+f(3-3)...f(n) = f(n-1)+f(n-2)+...+f(0)其中f(n-1) = f(n-2)+f(n-2)+...+f(0)那么,f(n) = 2*f(n-1)初始条件:f(1) = 1
public class Solution {public int jumpFloorII(int target) {if(target == 1){return 1;}return 2*jumpFloorII(target - 1);}}
10、矩形覆盖
```java 我们可以用21的小矩形横着或者竖着去覆盖更大的矩形 请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,从同一个方向看总共有多少种不同的方法?
比如n=3时,2*3的矩形块有3种不同的覆盖方法(从同一个方向看):
- 解法- 从n的这面方向看,小矩形长宽为1或者2,所以只能补1或者2- 即f(n)=f(n-1)+f(n-2)- 初始值:n=1,方法个数为1,n=2,方法个数为2```javapublic class Solution {public int rectCover(int target) {if(target <=2){return target;}int i=1,j=2,k;for(int t=3;t<=target;t++){k = i+j;i = j;j = k;}return j;}}
- 注意这种递归的循环表示方式,递归都可以用循环替代,递归代码简单,但是容易栈溢出
