剑指offer——其一
如何从已排好序的二维数组中寻找某数
private static boolean findnum(int num, int[][] arr) {
// TODO Auto-generated method stub
int i,j=0;
int r=arr.length,c=arr[0].length;
if(r==0) return false;
if(c==0) return false;
for(i=0;i<r;i++) {
if(num>=arr[i][0]&&num<=arr[i][c-1]) {
for(j=0;j<c;j++) {
if(num==arr[i][j])
return true;
}
}
}
return false;
}
思路:比较每行最大值和最小值,从而排除一整行.
替换字符串中的某种字符
直接调用java自带函数str.replace(src,des);
或用stringbuilder存储,遇上src就添加des
已知前序遍历和中序遍历,求该二叉树
/*public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
import java.util.Arrays;
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre.length == 0||in.length == 0)
return null;
TreeNode root=new TreeNode(pre[0]);
for(int i=0;i<in.length;i++){
if(in[i]==pre[0]){
root.left=reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
root.right=reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
break;
}
}
return root;
}
}
思路:从前序遍历中寻找根节点,用中序遍历确定左右子树,然后进行递归调用即可!(注意Arrays.copyOfRange()函数是左闭右开)
两个栈是这样成为队列的
思路:push()函数是一样的.而pop()则一个栈出一个栈进,就能将栈底元素调到栈顶.
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if (stack2.size() <= 0) {
while (stack1.size() != 0) {
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
}
Fibonacci玩出花
为了避免调用栈,可使用循环.
f(n+1)=f(n)+f(n-1)
当计算出f(n+1)时,sum=sum+one;
此时sum存的是f(n+1)的值,而one存的是f(n-1)的值.所以,用one=sum-one
使得one存储f(n)的值
class Solution {
public:
int Fibonacci(int n) {
if(n==0) return 0;
if(n==1) return 1;
int sum= 1;
int one = 0;
for(i=2;i<=n;i++){
sum+=one;
one=sum-one;
}
return sum;
}
};
同理小青蛙跳台阶也是此种解法!
变态跳台阶也是这样的,不过还能更直接,因为变态一次可以跳1个,2个...n个台阶,也就是f(n)=f(1)+f(2)+...+f(n-1)但是用数学归纳法,就可以清晰的得出,f(n)=2的(n-1)次方.用一个快速幂运算
public class Solution {
public int JumpFloorII(int n) {
if(n==1) return 1;
if(n==2) return 2;
int a=n-1;
int tmp=2;
int res=1;
while(a!=0){
if((a&1)==1)
res=res*tmp;
tmp=tmp*tmp;
a>>=1;
}
return res;
}
}
或者int res=1<<(n-1);
计算的就是2的n-1次方
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
public int NumberOf1(int n) {
int count=0;
while(n!=0){
count++;
n&=(n-1);
}
return count;
}
那个n&=(n-1);
是将最低位1变成0,是不是很神奇
快速幂运算
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
需要考虑exponent为负数的情况
public double Power(double base, int exponent) {
if(exponent==0) return 1;
if(exponent==1) return base;
int flag=0;
if(exponent<0)
{flag=1;
exponent=-exponent;}
double pingfang=base;
double res=1;
while(exponent!=0){
if((exponent&1)==1)
res=res*pingfang;
pingfang*=pingfang;
exponent>>=1;
}
if(flag==1)
return 1/res;
return res;
}
顺时针打印二维数组
需要好好分析一下特殊情况
while循环里面的事情如下
while(start<=row&&start<=col) {
while(y<=col) {
System.out.print(arr[x][y]+" ");
y++;
}y--;x++;
while(x<=row) {
System.out.print(arr[x][y]+" ");
//System.out.println(x+" "+y);
x++;
}x--;y--;
while(y>=start&&x>start) {
System.out.print(arr[x][y]+" ");
//System.out.println(x+" "+y);
y--;
}y++;x--;
while(x>start&&y>=start&&y!=col) {
System.out.print(arr[x][y]+" ");
x--;
}start++;
x=y=start;
row--;col--;
}
最小栈
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数,时间复杂度应为O(1).
Stack<Integer> Q=new Stack<Integer>();
Stack<Integer> Min=new Stack<Integer>();
public void push(int node) {
if(Q.isEmpty()||(node < Min.peek())){
Min.push(node);
}else{
Min.push(Min.peek());
}
Q.push(node);
}
public void pop() {
Q.pop();
Min.pop();
}
public int top() {
return Q.peek();
}
public int min() {
return Min.peek();
}
思路:应用双栈思想,存储每一种状态的最小值
或者直接构造新型数据结构,如
struct Node{
int val;
int min;};
输入两个整数序列,判断这两个整数序列顺序是否一致
public boolean IsPopOrder(int [] pushA,int [] popA) {
Stack<Integer> Q=new Stack<Integer>();
int i=0,j=0;
Q.push(pushA[i]);
i++;
if(Q.isEmpty()) return false;
while(i<pushA.length||j<pushA.length){
if(Q.peek()==popA[j]){
Q.pop();
j++;
}else{
if(i==pushA.length)
return false;
Q.push(pushA[i]);
i++;
}
}
if(Q.isEmpty()) return true;
else return false;
}