面试题 3二维数组的查找
public static boolean find(int [][] a,int val){
if(a==null) return false;
int rows=a.length;
int colums=a[0].length;
int i=0,j=colums-1;
while(i<rows&&j>=0){
if(a[i][j]==val) return true;
else if(a[i][j]>val) j--;
else i++;
}
return false;
}
面试题 4字符串中空格的替换,替换为20%,O(1)的空间复杂度
思路:先计算出替换后的总的长度,然后从后向前遍历,替换
public static void blankReplace(char[] c){
if(c==null) return;
int cnt=0;
for(int i=0;i<c.length;i++){
if(c[i]==' ') cnt++;
}
int j=c.length+2*cnt;
int i=c.length-1;
while(i>=0){
if(c[i]==' '){
c[j--]='%';
c[j--]='0';
c[j--]='2';
}
else c[j--]=c[i];
i--;
}
return;
}
面试题 5从尾到头打印单链表,可以使用栈,也可以用递归
public static void tailTohead(ListNode head){
if(head==null) return;
Stack<Integer> save=new Stack<>();
while(head!=null){
save.push(head.val);
head=head.next;
}
while(!save.isEmpty()){
System.out.print(save.pop());
}
}
public static void tailTohead(ListNode head){
if(head==null) return;
if(head.next!=null){
tailTohead(head.next);
}
System.out.print(head.val);
}
面试题 6重建二叉树,根据前序遍历和中序遍历递归构建左右子树,
public static class BinaryTreeNode {
int value;
BinaryTreeNode left;
BinaryTreeNode right;
}
public static BinaryTreeNode rebuildTree(int [] prerder,int [] inOrder){
if(prerder==null||inOrder==null||preOrder.length!=inOrder.length) return null;
return (preOrder,0,preOrder.length-1,inOrder,0,inOrder.length-1);
}
public static BinaryTreeNode helper(int [] preOrder,int ps,int pe,int [] inOrder,int is,int ie){
if(ps>pe) return null;
int val=preOrder[ps];
int index=is;
while(index<=ie&&inOrder[index]!=val){
index++;
}
BinaryTreeNode node=new BinaryTreeNode();
node.val=val;
node.left(preOrder,ps+1,ps+index-is,inOrder,is,index-1);
node.right(preOrder,ps+index-is+1,pe,inOrder,index+1,ie);
return node;
}
面试题 7用两个栈实现队列
核心思路:一个用来入队,一个辅助栈用来出队
public class stackToQueue{
Stack s1=new Stack<>();
Stack s2=new Stack<>();
public static void inPut(int x){
s1.push(x);
}
public static void outPut(int x){
is(s1.size()+s2.size()!=0){
if(!s2.isEmpty()){
System.out.print(s2.pop());
}
else{
helper();
System.out.print(s2.pop());
}
}
else return;
}
public static void helper(){
while(!s1.isEmpty()){
s2.push(s1.poll());
}
}
}
扩展 用2个队列实现一个栈
核心思想是 入栈时候就是入队到非空的队列,出栈就是把非空队列的n-1个元素转移到队列2中,然后弹出最后一个
public class queueToStack{
Queue q1=new LinkedList<>();
Queue q2=new LinkedList<>();
public static void inStack(int x){
if(q1.size()==0){
q2.offer(x);
}
else q1.offer(x);
}
public static void outStack(){
if(q1.size()+q2.size()!=0){
if(!q1.isEmpty(){
helper(q1,q2);
System.out.print(q1.poll());
}
else{
helper(q2,q1);
System.out.print(q2.poll());
}
}
}
public static void helper(Queue qu1,Queue qu2){
if(!qu1.isEmpty()){
while(qu1.size()>1){
qu2.offer(qu1.poll());
}
}
}
}
面试题 8旋转数组的最小值,二分查找的变形,数组可以含有重复元素
核心思想是中点和右边界进行比较,同时维护一个最小值,
public static int searchMin(int [] a){
if(a==null) return -1;
int i=0,j=a.length-1;
int min=a[0];
while(i<j-1){
int mid=i+(j-i)/2;
if(a[mid]>a[j]){
min=Math.min(min,a[i]);
i=mid+1;
}
else if(a[mid]<a[j]){
min=Math.min(min,a[mid]);
j=mid-1;
}
else{
j--;
}
}
min=Math.min(min,a[i]);
min=Math.min(min,a[mid]);
return min;
}
面试题 9求解裴波那契数列
递归和非递归版本
public static int feibo(int n){
if(n==0) return 0;
if(n==1) return 1;
return feibo(n-1)+feibo(n-2);
}
public static int feibo(int n){
if(n==0) return 0;
if(n==1) return 1;
int preone=1,pretwo=0,curr=0;
for(int i=2;i<=n;i++){
curr=preone+pretwo;
pretwo=preone;
preone=curr;
}
return curr;
}
面试题 10二进制中1的个数
核心思想是位操作,n&(n-1)相当于是把n最右侧的一个1变为0
public static int countBits(int n){
int cnt=0;
while(n!=0){
n=n&(n-1);
cnt++;
}
return cnt;
}
面试题 11数值的整数次方,double的int次幂
主要的注意点是整数的正负和零,以及非法输入
public static double powerExp(double base,int n){
if(equal(base)&&n<0) {
System.out.print("error");
return 0.0;
if(n>0){
return helper(base,n);
}
else return 1.0/helper(base,n);
}
}
public static equal(double a,double b){
double c=Math.abs(a-b);
if(c<0.0001){
return true;
}
return false;
}
public static double helper(double base,int n){
if(n==0) return 1.0;
if(n==1) return base;
double res=helper(base,n>>1);//递归计算
res=res*res;
if(n&1==1){
res=res*base;
}
return res;
}
面试题 12打印从1到最大的N位数
本质属于一个大数问题,用数组存储进行全排列,然后从第一个非零元素开始输出
public static void printMaxN(int n){
if(n<0) return;
int [] res=new int[n];//承载着n的信息
pailie(0,res);
}
public static void pailie(int index,int [] arr){
if(index>=arr.length){
prinNum(arr);
}
for(int i=0;i<=9;i++){
arr[index]=i;
pailie(index+1,arr);
}
}
public static void prinNum(int [] a){
int key=0;
while(key<a.length&&a[key]==0){
key++;
}
for(int i=key;i<a.length;i++ ){
System.out.print(a[i]);
}
if(key<a.length){
System.out.println();
}
}
面试题 13删除链表的结点O(1)
只访问这个结点,重点在于val的替换和结点的移位
public static void delNode(ListNode node){
if(node==null) return;
if(node.next==null) {
node==null;
return;
}
node.next=node.next.next;
node.val=node.next.val;
}
面试题 14调整数组顺序,奇数位于偶数前面,可以改变相对位置
解题思路使用双指针,一头一尾扫,一个遇到奇数同时另一个是偶数的时候交换
public static void reOrder(int [] a){
if(a.length<2) return;
int i=0,j=a.length-1;
while(i<j){
while((a[i]&1)==1&&i<j){
i++;
}
while((a[j]&1)==0&&i<j){
j--;
}
if(i<j){
int tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
}
}
面试题 15寻找链表中的倒数第K个数
核心就是快慢指针,快的先走K步然后慢的开始走,当快的走到头的时候慢指针的下一个就是倒数第K
public static ListNode findKth(ListNode head,int k){
if(head==null||k==0) return head;
ListNode fast=head,slow=head;
for(int i=0;i<n;i++){
fast=fast.next;
}
while(fast!=null){
fast=fast.next;
slow=slow.next;
}
return slow;
}
面试题 16反转链表
public static ListNode reverseList(ListNode head){
if(head==null||head.next==null) return head;
ListNode pre=null,curr=head,
while(curr!=null){
ListNode nex=curr.next;
curr.next=pre;
pre=curr;
curr=nex;
}
return pre;
}
面试题 17合并2个有序的链表
public static ListNode merge(ListNode head1,ListNode head2){
if(head1==null) return head2;
if(head2==null) return head1;
return helper(head1,head2);
}
public static ListNode helper(ListNode head1,ListNode head2){
ListNode dump=new ListNode(0);
ListNode p=dump;
while(head1!=null&&head2!=null){
if(head1.val<head2.val){
p.next=head1;
head1=head1.next;
p=p.next;
}
else{
p.next=head2;
head2=head2.next;
p=p.next;
}
}
while(head1!=null){
p.next=head1;
head1=head1.next;
p=p.next;
}
while(head2!=null){
p.next=head1;
head2=head2.next;
p=p.next;
}
return dump.next;
}
面试题 18树的子结构,判断一棵二叉树是不是另一个二叉树的子结构
思路:递归进行,使用的是或的操作,需要和子树进行区分
public static boolean isSubTree(TreeNode root1,TreeNode root2){
if(root1==null) return false;
if(root2==null) return true;
boolean res=false;
if(root1!=null&&root2!=null){
if(root1.val==root2.val){
res=match(root1,root2);
}
if(!res){
res=isSubTree(root1.left,root2);
}
if(!res){
res=isSubTree(root1.right,root2);
}
}
return res;
}
public static boolean match(TreeNode root1,TreeNode root2){
if(root1==null) return false;
if(root2==null) return true;
if(root1.val!=root2.val) return false;
return match(root1.left,root2.left)&&match(root1.right,root2.right);
}
面试题 19二叉树的镜像
public static TreeNode mirror(TreeNode root){
if(root==null) return root;
TreeNode tmp=mirror(root.left);
root.left=mirror(root.right);
root.right=tmp;
}
面试题 20顺时针打印矩阵
public static void printMatrx(int [][] a){
int m=a.length,n=a[0].length;
int start=0;
while(start*2<m&&start*2<n){
helper(a,start);
start++;
}
}
public static void helper(int [][]a ,int start){
int endx=a.length-1-start; //下边界
int endy=a[0].length-start-1;//右边界
for(int i=start;i<endy;i++){
System.out.print(a[start][i]+" ");
}
if(start<endx){
for(int i=start;i<endx;i++){
System.out.print(a[i][endy]+" ");
}
}
if(start<endx&&start<endy){
for(int i=endy-1;i>=start;i--){
System.out.print(a[endx][i]+" ");
}
}
if(start<endy&&start<endx-1){
for(int i=endx-1;i>=start;i--){
System.out.print(a[i][start]+" ");
}
}
}
面试题 21包含min的栈
使用一个辅助栈进行操作,最小栈存放的是数据站对应的最小的元素在数据栈中的位置,而且数量和数据站的数量一致。
public class {
Stsck s1=new Stack<>();
Stsck s2=new Stack<>();
public static void pushMin(int x){
if(s1.isEmpty()){
s1.push(x);
s2.push(0);
}
else{
int tmp=s1.get(s2.peek());
if(x<tmp){
s2.push(s1.size()-1);
}
else{
s2.push(s2.peek());
}
}
}
public static void popMin(){
if(s1.isEmpty()){
return;
}
else{
s2.pop();
return s1.pop();
}
}
public static int getMin(){
if(!s2.isEmpty()){
return s1.get(s2.peek());
}
else {
return 0;
}
}
}
//方法二:使用一个栈,如果小于目前的最小值则插2遍
Stack<Integer> s=new Stack<>();
int min=Integer.MAX_VALUE;
public static void push(int x){
if(x<=min){
s.push(min);
min=x;
}
s.push(x);
}
public static void pop(){
if(s.peek()==min){
s.pop();
min=s.pop();
}
else{
s.pop();
}
}
public static getmin(){
return min;
}
面试题 22从上往下打印二叉树
二叉树的层次遍历,使用一个队列来存储,
public static void printTree(TreeNode root){
if(root==null) return ;
Queue<TreeNode> q=new LinkedList<TreeNode>();
q.add(root);
while(!q.isEmpty()){
TreeNode node=q.poll();
System.out.peint(node.val);
if(node.left!=null){
q.add(node.left);
}
if(q.right!=null){
q.add(node.right);
}
}
}
public static List<List<Integer>> level(TreeNode root){
List<List<Integer>> res=new ArrayList<>();
if(root==null) return res;
Queue<TreeNode> q=new LinkedList<TreeNode>();
q.add(root);
while(!q.isEmpty()){
int n=q.size();
List<Integer> tmp=new ArrayList<>();
for(int i=0;i<n;i++){
TreeNode node=q.remove();
tmp.add(node.val);
if(node.left!=null){
q.add(node.left);
}
if(node.right!=null){
q.add(node.right);
}
}
res.add(tmp);
}
return res;
}
面试题 23二叉搜索树的后续遍历序列,判断一个整数数组是不是二叉搜索树的后续遍历结果
后续遍历是左右中 搜索树特点是是左<中<右
public static boolean searchBST(int [] a,int start,int end){
if(a.length<=0) return false;
int i=start;
while(i<end-1&&a[i]<a[end]){
i++;
}
int index=i;
while(i<end-1&&a[i]>a[end]){
i++;
}
if(i!=end-1) return false;
return searchBST(a,start,index-1)&&searchBST(a,index,end-1);
}
面试题 24二叉树中和为某一值的路径
递归思想 深度优先搜索
//判断是否存在
public static boolean pathSum(TreeNode root,int sum){
if(root==null) return false;
if(root.val==sum&&root.left==null&&root.right==null){
return true;
}
return pathSum(root.left,sum-root.val)||pathSum(root.right,sum-root.val);
}
//输出所有的,需要用一个容器来保存路径
int [] save=new save[1000];
List<List<Integer>> res=new ArrayList<>();
public static List<List<Integer>> pathsum(TreeNode root,int sum){
if(root==null) return res;
helper(root,sum,0);
}
public static void helper(TreeNode root,int sum,int index){
if(root==null) return;
save[index]=root.val;
if(root.val==sum&&root.left==null&&root.right==null){
List<Integer> tmp=new ArrayList<>();
for(int i=0;i<=index;i++){
tmp.add(save[i]);
}
res.add(tmp);
return;
}
helper(root.left,sum-root.val,index+1);
helper(root.right,sum-root.val,index+1);
}
相关扩展,输出所有的二叉树的路径
int [] save=new save[1000];
List<List<Integer>> res=new ArrayList<>();
public static List<List<Integer>> pathsum(TreeNode root){
if(root==null) return res;
helper(root,0);
}
public static void helper(TreeNode root,int index){
if(root==null) return;
save[index]=root.val;
if(root.left==null&&root.right==null){
List<Integer> tmp=new ArrayList<>();
for(int i=0;i<=index;i++){
tmp.add(save[i]);
}
res.add(tmp);
return;
}
helper(root.left,index+1);
helper(root.right,index+1);
}
面试题 27把一个二插搜索树转换成双向链表
中序遍历
public TreeNode Convert(TreeNode root) {
if(root==null)
return null;
if(root.left==null&&root.right==null)
return root;
// 1.将左子树构造成双链表,并返回链表头节点
TreeNode left = Convert(root.left);
TreeNode p = left;
// 2.定位至左子树双链表最后一个节点
while(p!=null&&p.right!=null){
p = p.right;
}
// 3.如果左子树链表不为空的话,将当前root追加到左子树链表
if(left!=null){
p.right = root;
root.left = p;
}
// 4.将右子树构造成双链表,并返回链表头节点
TreeNode right = Convert(root.right);
// 5.如果右子树链表不为空的话,将该链表追加到root节点之后
if(right!=null){
right.left = root;
root.right = right;
}
return left!=null?left:root;
}
面试题 28字符串的排列,不重复的
public static void Stringpailie(String s){
if(s.length()<=0) return;
char [] c=s.toCharArray();
helper(c,0,c.length-1);
}
public static void helper(char [] c,int from ,int to){
if(to<1||from>c.length) return;
if(from==to){
for(int i=0;i<=to;i++){
System.out.print(c[i]);
}
System.out.println();
}
for(int i=from;i<=to;i++){
swap(c,from,i);
helper(c,from+1,to);
swap(c,from,i);
}
}
public static void swap(char [] c,int a,int b){
char tmp=c[a];
c[a]=c[b];
c[b]=tmp;
}
面试题 29数组中出现此数超过一半的数字
方法一可以使用hash记录出现次数,也可以排序在处理,最好的是使用摩尔投票方法。
public static int majorityNum(int [] a){
if(a==null) return -1;
if(a.length==1) return a[0];
int times=0;
int save=0;
for(int i=0;i<a.length;i++){
if(times==0){
save=a[i];
times=1;
}
else if(save==a[i]){
times++;
}
else{
times--;
}
}
int cnt=0;
for(int i=0;i<a.length;i++){
if(a[i]==save) cnt++;
}
if(cnt>a.length/2){
return save;
}
}
扩展:寻找数组中出现次数大于n/3的数,
public static List<Integer> majorityNum(int [] a){
List<Integer> res=new ArrayList<>();
if(a==null) return res;
//寻找
int m=0,n=1,cm=0,cn=0;
for(int i=0;i<a.length;i++){
if(a[i]==m){
cm++;
}
else if(a[i]==n){
cn++;
}
else if(cm==0){
m=a[i];
cm=1;
}
else if(cn==0){
n=a[i];
cn=1;
}
else {
cm--;cn--;
}
}
//验证
int cnt1=0,cnt2=0;
for(int i=0;i<a.length;i++){
if(a[i]==m) cnt1++;
if(a[i]==n) cnt2++;
}
if(cnt1>a.length/3){
res.add(m);
}
if(cnt2>a.length/3){
res.add(n);
}
return res;
}
面试题 30最小的K个数,快排切分思想,使得小于第K个数的都在左侧,大于第K个数的都在右侧
时间复杂度是O(N),也可以使用维护一个小顶堆,用优先队列即可。
//方案1
public static int[] smallKMum(int [] a,int s){
int[] res=new int[k];
if(a==null||k>a.length) return res;
int left=0,right=a.length-1;
int index=partition(a,left,right);
int k=a.length-s;
while(index!=k-1){
if(index>k-1){
index=partition(a,left,index-1);
}
else{
index=partition(a,index+1,right);
}
}
for(int i=0;i<k;i++){
res[i]=a[i];
}
return res;
}
public static int partition(int [] a,int from,int to){
if(a==null||from>to) return -1;
int base=a[from];
while(from<to){
while(from<to&&a[to]>base){
to--;
}
if(from<to){
a[from++]=a[to];
}
while(from<to&&a[from]<base){
from++;
}
if(from<to){
a[to--]=a[from];
}
}
a[from]=base;
return from;
}
//方案2
public static int[] minKMum(int [] a,int k){
int[] res=new int[k];
if(a==null||k>a.length) return res;
Queue<Integer> q=new priorityQueue<>();
for(int i=0;i<a.length;i++){
if(q.size()<k){
q.offer(a[i]);
}
else if(a[i]<q.peek()){
q.poll();
q.offer(a[i]);
}
}
int i=0;
while(!q.isEmpty()){
res[i++]=q.poll();
}
return res;
}
扩展:找到第K大的数即可
public static int bigKMum(int [] a,int from,int to,int k){
if(a==null||k>a.length) return -1;
if(from<=to){
int index=partition(a,from,to);
int num=to-index+1;
if(num==k) return a[num];
else if(num>k){
return bigKMum(a,index+1,to,k);
}
else{
return bigKMum(a,from,index-1,k-index);
}
}
return -1;
}
面试题 31连续子数组的最大和(最大序列和)
public static int maxSum(int [] a){
if(a==null) return -1;
if(a.length==1) return a[0];
int max=0,sum=0;
for(int i=0;i<a.length;i++){
sum=sum+a[i];
if(sum>max){
max=sum;
}
if(sum<0) sum=0;
}
return max;
}
面试题 32从1到N的整数中1出现的次数。
数位递归
面试题 34第K个丑数,规定1是第一个丑数
public static int getUglyNum(int k){
if(k==1) return 1;
if(k<1) return -1;
int [] num=new int[k];
num[0]=1;
int index=1;
int p2=0;
int p3=0;
int p5=0;
while(index<k){
num[index]=min3(num[p2]*2,num[p3]*3,num[p5]*5);
while(num[p2]*2<=num[index]){
p2++;
}
while(num[p3]*3<=num[index]){
p3++;
}
while(num[p5]*5<=num[index]){
p5++;
}
index++;
}
return num[index-1];
}
public static int min3(int a,int b,int c){
int res=a;
if(res>b) res=b;
if(res>c) res=c;
return res;
}
面试题 35第一个只出现一次的字符
时间复杂度是O(N),使用的是LinkedHashMap
public static char findOnce(String s){
char res=' ';
Map<Character,Integer> m=new LinkedHashMap<>();
for(int i=0;i<s.length();i++){
if(m.containsKey(s.charAt(i))){
m.put(s.charAt(i),-2);
}
else{
m.put(s.charAt(i),i);
}
}
//遍历LinkedHashMap
Iterator<Entry<Character,Integer>> ite=m.entrySet().iterator();
int min=Integer.MAX_VALUE;
while(ite.hasNext()){
Entry<Character, Integer> entry = iterator.next();
if(enter.getValue()>=0&&enter.getValue<min){
min=entry.getValue;
res=entry.getKey();
}
}
return res;
}
面试题 36数组中的逆序对
使用归并排序实现,求的是数量
int cnt=0;
public static int inversPair(int [] a){
if(a.length<=1) return 0;
sort(a,o,a.length-1);
}
public static void sort(int [] a,int from,int to){
if(a==null||from>=to) return;
if(from<to){
int middle=from+(to-from)/2;
sort(a,from,middle);
sort(a,middle+1,to);
merge(a,from,middle,to);
}
}
public static void merge(int [] a,int from,int middle,int to){
if(a==null||from>=to) return;
int[] tmp=new int[to-from+1];
int i=from,j=middle+1,k=0;
while(i<=middle&&j<=to){
if(a[i]<=a[j]){
tmp[k++]=a[i++];
}
else{
cnt+=j-k;//计算逆序对
tmp[k++]=a[j++];
}
}
while(i<=middle){
tmp[k++]=a[i++];
}
while(j<=to){
tmp[k++]=a[j++];
}
for(int i=0;i<k;i++){
a[from+i]=tmp[i];
}
}
面试题 37链表的第一个公共节点
方法是先比较长度,比较长的那个先移位,两个长度一样了再比较
public static LinstNode commenNode(ListNode head1,ListNode head2){
if(head1==null||head2==null) return null;
int m=getLen(head1);
int n=getLen(head2);
int diff=Math.abs(m-n);
while(diff>0){
if(m>n) head1=head1.next;
else head2=head2.next;
diff--;
}
while(head1!=null&&head2!=null){
if(head1==head2){
return head1;
}
else{
head1=head1.next;
head2=head2.next;
}
}
return null;
}
public static int getLen(ListNode head){
int res=0;
LinstNode p=head;
while(p!=null){
p=p,next;
res++;
}
return res;
}
面试题 38目标数字在有序数组中出现的次数
二分查找的变形,找到第一次出现的位置和最后一次出现的位置,然后就可以求出来了
public static int getCountK(int[] a,int k){
if(a==null) return 0;
int from=getFirst(a,k);
int to=getLast(a,k);
System.out.println(from+" "+to);
if(from>-1&&to>-1){
return to-from+1;
}
else return 0;
}
public static int getLast(int[] a,int k){
if(a==null) return -1;
int l=0,r=a.length-1;
while(l<r-1){
int mid=l+(r-l)/2;
if(a[mid]>k){
r=mid-1;
}
else l=mid;
}
if(a[r]==k) return r;
else if(a[l]==k) return l;
return -1;
}
public static int getFirst(int[] a,int k){
if(a==null) return -1;
int l=0,r=a.length-1;
while(l<r-1){
int mid=l+(r-l)/2;
if(a[mid]<k){
l=mid+1;
}
else r=mid;
}
if(a[l]==k) return l;
else if(a[r]==k) return r;
return -1;
}
面试题 39二叉树的最大深度
public static int maxLen(TreeeNode root){
if(root==null) return 0;
return Math.max(maxLen(root.left),maxLen(root.right))+1;
}
扩展 最小深度
public static int minLen(TreeeNode root){
if(root==null) return 0;
if(root.left==null) return minLen(root.right)+1;
if(root.right==null) return minLen(root.left)+1;
return Math.min(minLen(root.left),minLen(root.right))+1;
}
面试题 40数组中只出现一次的数字
使用异或操作
public static int findOnly(int[] a){
if(a.length==1) return a[0];
int res=0;
for(int i=0;i<a.length;i++){
res=res^a[i];
}
return res;
}
扩展 只出现一次的两个数字,还是使用异或
public static int[] findOnly(int[] a){
int[] res=new int[2];
int tmp=0;
for(int i=0;i<a.length;i++){
tmp=tmp^a[i];
}
int index=helper(tmp);
int num1=0,num2=0;
for(int i=0;i<a.length;i++){
if(((a[i]>>index)&1)==0){
num1=num1^a[i];
}
else{
num2=num2^a[i];
}
}
res[0]=num1;
res[1]=num2;
return res;
}
public static int helper(int a){
int res=0;
while((a&1)==0){
res++;
a=a>>1;
}
return res;
}
面试题 41数组中和为S的两个数
使用hashmap,
public static int[] twoSum(int[] a,int sum){
int[] res=new int[2];
if(res==null) return res;
HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
for(int i=0;i<a.length;i++){
if(map.get(sum-a[i])!=null){
res[0]=i;
res[1]=map.get(sum-a[i]);
}
else map.put(a[i],i);
}
return res;
}
面试题 42单词反转 i love you ====>you love i
使用split()
public static String WordReverse(String s){
if(s==null) return "";
String [] save=s.split(" ");
StringBuffer sb=new StringBuffer();
for(int i=save.length-1;i>=0;i--){
if(save[i]!=" "){
sb.append(save[i]);
sb.append(" ");
}
}
return sb.length()==0? "":sb.substring(0,sb.length()-1).toString();
}
扩展 三次翻转法
public static String WordReverse(String s,int k){
if(s==null) return "";
char[] c=s.toCharArray();
Reverse(c,0,k-1);
Reverse(c,k,c.length-1);
Reverse(c,0,c.length-1);
return String.()
}
public static void Reverse(char[] c,int from,int to){
if(from>=to) return;
while(from<to){
char tmp=c[from];
c[from]=c[to];
c[to]=tmp;
from++;to--;
}
}
面试题 45圆圈中最后剩下的数字,约瑟夫环
public static int Reamin(int n,int m){
if(n<1||m<1) return -1;
int last=0;
for(int i=2;i<=n;i++){
last=(last+m)%i;
}
return last;
}
面试题 47不用加号实现加法,位运算
public static int plus(int a,int b){
while(b!=0){
int c=a^b;
b=(a&b)<<1;
a=c;
}
return a;
}
面试题 59判断二叉树是不是镜像二叉树
方法是前序遍历和镜像前序遍历比较
public static boolean iSMirrorTree(TreeNode root){
if(root==null) return false;
return helper(root,root);
}
public static boolean helper(TreeNode root1,TreeNode root2){
if(root1==null&&root2==null) return true;
if(root1==null||root2==null) return false;
if(root1.val!=root2.val) return false;
return helper(root1.left,root2.right)&&helper(root1.right,root2.left);
}
剑指offer ---java版本
最新推荐文章于 2021-03-17 17:33:58 发布