前22道题中需要二刷的有
题目4 重建二叉树
题目6 旋转数组的最小数字
题目12 数值的整次方
题目21 栈的压入弹出序列
题目1 二维数组的查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
public boolean Find(int target, int [][] array) {
if(array==null||array.length<1||array[0].length<1)
{
return false;
}
int startx=0;
int starty=array.length-1;
while(startx<array.length&&starty>-1)
{
if(array[startx][starty]>target)
{
starty--;
}else if(array[startx][starty]<target)
{
startx++;
}else
{
return true;
}
}
return false;
}总结:因为这儿二维数组都是有序的所以要利用这个条件
题目2 替换空格
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
public String replaceSpace(StringBuffer str) {
char[] chars = str.toString().toCharArray();
int count=0;
for(int i=0;i<chars.length;i++)
{
if(chars[i]==' ')
count++;
}
char[] res=new char[chars.length+count*2];//承载结果的数组,一个空格对应这个三个字符
int index=res.length-1;
for(int i=chars.length-1;i>=0;i--)//倒着走,并且使用一个全局的index走新的数组
{
if(chars[i]!=' ')
{
res[index--]=chars[i];
}else
{
res[index--]='0';
res[index--]='2';
res[index--]='%';
}
}
return String.valueOf(res);
}总结:for循环走原数组,index走新的数组
题目3 链表的逆置
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ListNode pre=null;
ListNode next=null;
while(listNode!=null)
{
next=listNode.next;
listNode.next=pre;
pre=listNode;
listNode=next;
}
ArrayList<Integer> list=new ArrayList<Integer>();
while(pre!=null)
{
list.add(pre.val);
pre=pre.next;
}
return list;
}总结:需要注意的点
1,需要提前定义的变量pre,next都是指向空的
2,最后返回的是pre,这个指向的是新的头,因为cur已经指向了null
3,我们使用next来保留下一个需要处理的结点
4,当前的结点的next指向pre
5,pre变成了当前的结点
6,当前结点变成了后面的结点
next=listNode.next;//3,
listNode.next=pre;//4,
pre=listNode;//5,
listNode=next;//6,题目4 重建二叉树 (二刷)
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre == null || in == null) {
return null;
}
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < in.length; i++) {
map.put(in[i], i);
}
return preIn(pre, 0, pre.length - 1, in, 0, in.length - 1, map);
}
public static TreeNode preIn(int[] p, int pi, int pj, int[] n, int ni, int nj,
HashMap<Integer, Integer> map) {
if (pi > pj) { //base case
return null;
}
TreeNode head = new TreeNode(p[pi]);
int index = map.get(p[pi]);
head.left = preIn(p, pi + 1, pi + index - ni, n, ni, index - 1, map);
head.right = preIn(p, pi + index - ni + 1, pj, n, index + 1, nj, map);
return head;
}
}总结:
1,需要一个map,我们从前序到中序的映射,需要通过这个map
2,这个map在递归之前将中序的内容和下标依次存入
3,base case start前序 > end中序 极端情况是只有一个数的时候
4,index是我们通过映射得到的在中序的下标,index-start中序 中序中对应的左子树
题目5 两个栈实现一个队列
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int num)
{
stack1.push(num);
}
public int pop()
{
if(stack2.isEmpty())
{
while(!stack1.isEmpty())
{
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
}题目6 旋转数组的最小数字 (二刷)
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
public int minNumberInRotateArray(int [] arr) {
int start=0;
int end=arr.length-1;
int mid=0;
while(start<end)
{
/*
注意这两个情况
*/
if(start+1==end) break;
if(arr[start]<arr[end]) return arr[start];
mid=(start+end)/2;
if(arr[mid]>arr[start])
{
start=mid;//为什么不使用mid+1,因为mid有可能就是最后的结果
continue;
}
if(arr[mid]<arr[start])
{
end=mid;
continue;
}
//如果是其他的情况
//start,end,min相同
while(start<=mid)
{
if(arr[start]==arr[mid])
{
start++;
}
// 3 3 4 5 3 3 3 3 3
else if(arr[start]>arr[mid])
{
return arr[mid];
}
else if(arr[start]<arr[mid])
{
return arr[start];
}
}
}
/*
5 4
3 4
最后剩下的如果是两个
*/
return Math.min(arr[start],arr[end]);
}总结:
1,最后我们剩下的是两个数字,所以需要注意的两个位置
循环条件 start<end
程序结束位置 return Math.min(arr[start],arr[end]);
2,程序最开始的 if(start+1==end) break;
3,start=mid;//为什么不使用mid+1,因为mid有可能就是最后的结果
4,特殊情况的处理,我们列举出三种情况
3 4 5 3 3 3 3 3//case 1 3 1 2 3 3 3 3 3//case 2 3 3 3 3 3 4 5 6
情况1 2 都可以直接返回,因为我们特殊情况是while(start<=end)
题目7 斐波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39
public int Fibonacci(int n) {
if(n==0) return 0;
if(n==1||n==2) return 1;
int pre=1;
int prepre=1;
int cur=0;
for(int i=3;i<=n;i++)
{
cur=pre+prepre;
prepre=pre;
pre=cur;
}
return cur;
}题目8 跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
public int JumpFloor(int n) {
if(n==0) return 0;
if(n==1||n==2) return n;
int pre=2;
int prepre=1;
int cur=0;
for(int i=3;i<=n;i++)
{
cur=pre+prepre;
prepre=pre;
pre=cur;
}
return cur;
}题目9 疯狂跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
public class Solution {
public int JumpFloorII(int target) {
int tmp=2;
int res=1;
target=target-1;
for(;target!=0;target>>>=1)
{
if((target&1)!=0)
{
res=tmp*res;
}
tmp=tmp*tmp;
}
return res;
}
}总结:2^(n-1)
题目10 矩形覆盖
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
public class Solution {
public int RectCover(int n) {
if(n==0) return 0;
if(n==1||n==2) return n;
int pre=2;
int prepre=1;
int cur=0;
for(int i=3;i<=n;i++)
{
cur=pre+prepre;
prepre=pre;
pre=cur;
}
return cur;
}
}题目11 二进制中1的个数
public int NumberOf1(int n) {
int res=0;
while(n!=0)
{
n-=n&(~n+1);//n=n&(n-1);
res++;
}
return res;
}总结:两种写法
题目12 数值的整次方 二刷
public double Power(double base, int exponent) {
if(exponent==0 && base != 0)//情况1 非0数的0次方
return 1;
if(exponent==1)//情况2 任何数的1次方
return base;
if(base == 0 && exponent <= 0){//情况3 0的0次方没有意义
throw new RuntimeException();
}
if(base ==0 && exponent>0){ //0的次方
return 0;
}
//以上全部都是判断情况
int n= exponent;
if(exponent<0){
n = -exponent;
}
double result=Power(base,n>>1);
result*=result;
if((n&1)==1)
result*=base;
if(exponent<0)
result=1/result;
return result;
}总结:
核心代码
double result=Power(base,n>>1);
result*=result;
if((n&1)==1)
result*=base; 举一个例子
2^11
11的二进制形式为1011
我们将2^*(101)B算出来,任何让它多加一个零变成1010B,也就是自己和自己相乘,然后判断当前的为是0还是1,如果是0的话,不管,如果是1的话,我们还要多乘一个base
题目13 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
public void reOrderArray(int [] arr) {
int index=0;
int index2=0;
while(index<arr.length)
{
/*
index指向第一个偶数
index2指向第一个奇数
*/
while(index<arr.length&&(arr[index]&1)!=0)
{
index++;
}
//index 找到偶数
//index2 找到奇数
index2=index+1;
while(index2<arr.length&&(arr[index2]&1)==0)
{
index2++;
}
if(index2<arr.length)
{
int tmp=arr[index2];
for(int i=index2;i>index;i--)
{
arr[i]=arr[i-1];
}
arr[index++]=tmp;
}else
{
break;
}
}
}题目14 链表中倒数第k个结点
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null) return null;
ListNode cur=head;
int count=0;
while(cur!=null)
{
cur=cur.next;
count++;
}
if(count<k) return null;
cur=head;
while(cur!=null)
{
cur=cur.next;
k--;
count++;
}
cur=head;
for(int i=k;i!=0;i++)
{
cur=cur.next;
}
return cur;
}题目15 链表逆置
public ListNode ReverseList(ListNode head) {
ListNode next=null;
ListNode pre=null;
ListNode cur=head;
while(cur!=null)
{
next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}题目16 合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
public ListNode Merge(ListNode head1,ListNode head2) {
if(head1==null)
{
return head2;
}else if(head2==null)
{
return head1;
}
ListNode head=head1.val<head2.val?head1:head2;
ListNode cur1=head==head1?head1:head2;
ListNode cur2=head==head1?head2:head1;
ListNode next=null;
ListNode pre=null;
while(cur1!=null&&cur2!=null)
{
if(cur1.val<=cur2.val)
{
pre=cur1;
cur1=cur1.next;
}else
{
next=cur2.next;
pre.next=cur2;
cur2.next=cur1;
pre=cur2;
cur2=next;
}
}
pre.next=cur1==null?cur2:cur1;
return head;
}总结:我们的pre指针要时刻的指向上一次操作的结点,为了最后的连接
题目17 树的子结构
public boolean HasSubtree(TreeNode node1,TreeNode node2) {
if(node2==null) return false;
return isContained(node1,node2);
}
public boolean isContained(TreeNode node1,TreeNode node2) {
if (node2 == null) {
return true;
}
if (node1 == null) {
return false;
}
return isCheck(node1,node2)||isContained(node1.left,node2)||isContained(node1.right,node2);
}
public static boolean isCheck(TreeNode node1, TreeNode node2)
{
if(node2==null)
{
return true;
}
if(node1==null||node1.val!=node2.val){
return false;
}
return isCheck(node1.left,node2.left)&&isCheck(node1.right, node2.right);
}题目18 镜像二叉树
public void Mirror(TreeNode root) {
if(root==null) return ;
TreeNode tmp=root.right;
root.right=root.left;
root.left=tmp;
Mirror(root.left);
Mirror(root.right);
}题目19 顺时针打印矩阵
public ArrayList<Integer> printMatrix(int[][] arr)
{
ArrayList<Integer> list=new ArrayList<>();
int startl=0;
int startc=0;
int endl=arr.length-1;
int endc=arr[0].length-1;
while(startc<=endc&&startl<=endl)
{
printMatrixEdge(arr,startl++,startc++,endl--,endc--,list);
}
return list;
}
public static void printMatrixEdge(int[][] arr,int startl,int startc,int endl,int endc,ArrayList<Integer> list)
{
if(startl==endl)//只有一行
{
for(int i=startc;i<=endc;i++)
{
list.add(arr[startl][i]);
}
}else if(startc==endc)//只有一列
{
for(int i=startl;i<=endl;i++)
{
list.add(arr[i][startc]);
}
}else
{
int curl=startl;
int curc=startc;
while(curc<endc)
{
list.add(arr[startl][curc]);
curc++;
}
while(curl<endl)
{
list.add(arr[curl][endc]);
curl++;
}
while(curc>startc)
{
list.add(arr[endl][curc]);
curc--;
}
while(curl>startl)
{
list.add(arr[curl][startc]);
curl--;
}
}
}题目20 包含min函数的栈
private Stack<Integer> stack=new Stack<>();
private Stack<Integer> minStack=new Stack<>();
public void push(int node) {
stack.push(node);
if(stack.size()==1)
{
minStack.push(node);
}else
{
int curValue=minStack.peek();
if(curValue>=node){
minStack.push(node);
}else {
minStack.push(curValue);
}
}
}
public void pop() {
stack.pop();
minStack.pop();
}
public int top() {
return stack.peek();
}
public int min() {
return minStack.peek();
}题目21 栈的压入弹出序列 二刷
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
public boolean IsPopOrder(int [] lpush,int [] lpop) {
int index=0;
Stack<Integer> stack=new Stack<>();
for(int i=0;i<lpush.length;i++)
{
stack.push(lpush[i]);
while(!stack.isEmpty()&&stack.peek()==lpop[index])
{
stack.pop();
index++;
}
}
return stack.isEmpty();
}题目22 层次遍历
public ArrayList<Integer> PrintFromTopToBottom(TreeNode head) {
ArrayList<Integer> list=new ArrayList<>();
if(head==null) return list;
LinkedList<TreeNode> queue=new LinkedList<>();
queue.addLast(head);
while(!queue.isEmpty())
{
TreeNode node = queue.pollFirst();
list.add(node.val);
if(node.left!=null)
{
queue.addLast(node.left);
}
if(node.right!=null)
{
queue.addLast(node.right);
}
}
return list;
}
京公网安备 11010502036488号