java编写实现更新_剑指offer编程题java实现(正在更新)

面试题三:查找二维数组中元素问题

public static voidmain(String[] args){int[][] num = {{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}};

search(num,7);

}public static void search(int[][] arr,inttarget){int rows =arr.length;int columns = arr[0].length;int row = 0;int column = columns-1;while(row<=rows&&column>=0){if(target==arr[row][column]){

System.out.println(target+"在第"+row+"行,第"+column+"列");break;

}if(target>arr[row][column]){

row++;

}if(target

column--;

}

}

}

面试题四:替换字符串中的空格

延伸:1.合并两个字符串     2.两个有序数组,将一个插入到另一个,并保证有序。    从后面开始会减少元素移动的次数?

public static voidmain(String[] args){int[][] num = {{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}};

String str= "we are happy";

replaceBlank(str);

}public static voidreplaceBlank(String str){char[] charOld =str.toCharArray();char[] charNew = new char[100];for(int j = 0;j

charNew[j]=charOld[j];

}int blank = 0;for(int i = 0;i

blank++;

}

}int lengthFront = charOld.length-1;int lengthBack = charOld.length+2*blank-1;while(lengthFront>=0&&lengthBack>=0){if(charNew[lengthFront]!=' '){

charNew[lengthBack--] =charNew[lengthFront];

}else{

charNew[lengthBack--] = '0';

charNew[lengthBack--] = '2';

charNew[lengthBack--] = '%';

lengthFront--;

}

lengthFront--;

}

System.out.println(charNew);

}

面试题5.从尾到头打印链表(利用栈或递归来实现)

构建链表

public classListNode {private intvalue;privateListNode next;public ListNode(intvalue){this.value =value;

}public ListNode(intvalue,ListNode next){this.value =value;this.next =next;

}public void setValue(intvalue){this.value =value;

}public intgetValue(ListNode node){returnnode.value;

}public voidsetNext(ListNode next){this.next =next;

}publicListNode getNext(){return this.next;

}

}

Stack s = new Stack();     栈                                                 public static void method(head){    递归,但是链表长度较长时就不要用

ListNode p = head;                                                                      if(head!=null){

while(p!=null){                                                                                 if(head.getNext()!=null){

stack.push(p.getValue());                                                                      method(head.getNext);

p=p.getNext();                                                                                }

}                                                                                                  System.out.println(head.getValue());

while(!s.isEmpty){                                                                    }

System.out.println(s.pop());                                             }

}

面试题六:根据前序和中序输出构造二叉树

建二叉树

public classBinaryTreeNode {private intvalue;privateBinaryTreeNode left;privateBinaryTreeNode right;public BinaryTreeNode(intvalue){this.value =value;

}public BinaryTreeNode(intvalue,BinaryTreeNode left,BinaryTreeNode right){this.value =value;this.left =left;this.right =right;

}public intgetValue( ){return this.value;

}public voidsetValue(BinaryTreeNode node){this.value =value;

}public voidsetLeft(BinaryTreeNode node){this.left =node;

}public voidsetRight(BinaryTreeNode node){this.right =node;

}publicBinaryTreeNode getLeft( ){return this.left;

}publicBinaryTreeNode getRight( ){return this.right;

}

}

根据前序找根节点,然后判断根节点在中序输出中的位置,根节点左边的就是左子树,右边的就是右子树,然后递归调用此方法。

public static voidmain(String[] args){int[][] num = {{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}};int[] frontOrder = {1,2,4,7,3,5,6,8};int[] inOrder = {4,7,2,1,5,3,8,6};

BinaryTreeNode root=BinaryTree(frontOrder,inOrder);

printPostOrder(root);

}public static voidprintPostOrder(BinaryTreeNode root){if(root!=null){

printPostOrder(root.getLeft( ));

printPostOrder(root.getRight( ));

System.out.println(root.getValue());

}

}public static BinaryTreeNode BinaryTree(int[] frontOrder,int[] inOrder){

BinaryTreeNode root= new BinaryTreeNode(frontOrder[0]);

root.setLeft(null);

root.setRight(null);int leftLength = 0;for(int i =0;i

}else{

leftLength++;

}

}int rightLength = inOrder.length-leftLength-1;if(leftLength>0){int[] leftFrontOrder = new int[leftLength];int[] leftInorder = new int[leftLength];for(int j = 0;j

leftFrontOrder[j]= frontOrder[j+1];

leftInorder[j]=inOrder[j];

}

BinaryTreeNode leftRoot=BinaryTree(leftFrontOrder,leftInorder);

root.setLeft(leftRoot);

}if(rightLength>0){int[] rightFrontOrder = new int[rightLength];int[] rightInorder = new int[rightLength];for(int k = 0;k

rightFrontOrder[k]= frontOrder[k+1+leftLength];

rightInorder[k]= inOrder[k+1+leftLength];

}

BinaryTreeNode rightRoot=BinaryTree(rightFrontOrder,rightInorder);

root.setRight(rightRoot);

}returnroot;

}

面试题七.两个栈实现一个队列

先用一个栈存,这样就是倒序,然后依次取出放入另一个栈,这就是正序了,然后再取出,就和队列一样了。

public class sQueue{

Stack s1 = new Stack();

Stack s2 = new Stack();public voidappendTrail(T append){

s1.push(append);

}public T deleteHead(Stacks){if(s1==null){if(s2==null){try{throw new Exception("队列为空");

}catch(Exception e ){

e.printStackTrace();

}

}

}while(s1.size()>0){

s2.push(s1.pop());

}returns2.pop();

}

}

面试题:将企业中员工年龄排序,使用一个长度100的数组作为辅助空间,记录每个年龄出现的次数,然后按照这个记录的次数输出年龄

public static void sort(int[] ages,intlength){int largeAge = 99;int[] timeAge = new int[largeAge+1];

length=ages.length;if(ages==null||length<0){return;

}for(int i = 0;i99){return;

}

timeAge[age]++;

}int index = 0;for(int j = 0;j<=largeAge;j++){for(int k =0;k

ages[index]=j;

index++;

}

}

}

面试题八.求旋转数组的最小值

public static int findMin(int[] num){if(num==null||num.length<=0){return 0;

}int middle = num.length/2;int front = 0;int back = num.length-1;while(num[front]>num[back]){if(back-front==1){

middle=back;break;

}

middle= (front+back)/2;if(num[middle]==num[front]&&num[front]==num[back]){ 10111 这种情况就需要顺序遍历来找了return 0;

}if(num[middle]>num[front]){

front=middle;

}if(num[middle]

back=middle;

}

}returnnum[middle];

}

面试题九:斐波那契数列

f(n) = f(n-1)+f(n-2)      类似的有上台阶问题,一次能迈1个或2个台阶,问有多少种方法上楼梯。迈上终点之前肯定是迈了一步或是两步,那n-1个台阶的方法数加上n-2个台阶的方法数就是n个台阶的方法数。

那么如果一次能迈的台阶数没有限制呢,1,2,3,。。。n       用归纳法得出f(n) = 2的n-1次方

public static int fibonaci(intn){if(n==0){return 0;

}else if(n==1){return 1;

}else{int front = 0;int back =1;int x =0;for(int i =0;i<=n;i++){

x= front+back;

front=back;

back=x;

}returnx;

}

}

类似的格子填充问题

72eb0bc881ed85eb3b5ce97812365e5a.png

面试题十:二进制中1的个数

正数(1,0x7FFFFFFF)负数(0x80000000,0xFFFFFFFF)

解法:十进制中的1二进制表示为00000001,我们可以借助它和要检验的二进制数A相与,这样,就可以根据结果获知 A中最后一位是0还是1。

1.第一次相与后,把A右移一位,再次相与,这样依次右移就可以知道每一位是0是1。但是当A为负数时这种方法不可行。移位前是负数的话,就要保证移位后是负数,这样移位后最高位自动置1.

2.第一次相与后,将00000001依次向左移动一位,这是一种较好的方法,因为不确定A的大小,移动可能会产生影响。

3.最好的解法:比如一个1100,将1100减去1是1011,然后将1100和1011相与得出1000,这样1100中最右边的1就变为0。再执行一次的话就变成0000。这样执行n次后A变为0,那么A中就有n个1.

把一个二进制A和B=(A-1)相与,那么A的最后一个1变0.

public static voidmain(String[] args){int n =10;int c =count(n);

System.out.println(c);

}public static int count(intn){int num = 0;while(n!=0){

n= n&(n-1);

num++;

}returnnum;

}

相关题目1:一个数是否为2的整数次方。

解法:一个数如果是2的整数次方,那么它的二进制有且只有一个1.

相关题目2:求从一个二进制变为另一个需要改变多少位。

解法:两数异或,统计二进制结果中1的数目。

面试题11.数的整数次幂

base为0,指数为负的情况也要考虑到。 指数为负,把指数取正,然后结果取倒数。

public static void main(String[] args){

double a = power(2,5);

System.out.println(a);

}

public static  double power(double base,int exponent){

if(exponent ==0 ){

return 1;

}

if(exponent == 1){

return base;

}

if(exponent>>1==0){

int exponent1 = exponent>>1;

double result = power(base,exponent1);

return result*result;

}else{

int exponent2 = exponent-1;

double result = power(base,exponent2);

return result*base;

}

}

面试题十二:输出1到n位最大整数

如果按照最简单的循环输出,会遇到边界问题,n非常大的话,int甚至long都不能满足需求,所以这里需要用数组或者是字符串来表示要输出的数字。

如果面试题给定了一个n位整数,那么就是大数问题,用字符串来解决。

给定两个整数相加求结果,也是大数问题。

public static voidmain(String[] args){

bigData(3);

}public static void bigData(intn){char[] num = new char[n];for(int i = 0;i

num[i]= '0';

}boolean end = false;while(!end){

num[n-1]++;for(int k =n-1;k>0;k--){if(num[k]=='9'+1){

num[k]= '0';

num[k-1]++;

}

}if(num[0]=='9'+1){

end= true;break;

}boolean out = false;for(int j =0;j

}else{

out= true;

System.out.print(num[j]);

}

}

System.out.println("...");

}

}

面试题十三:在O(1)时间内删除单向链表中的一个节点

思路:如果从首部开始依次查找,那么时间是O(n).

既然我们知道要删除的结点i,那么我们就知道它指向的下一个结点j,那么我们可以将j的内容复制到i,然后将i的指针指向j的下一个结点,这样虽然看起来我们删除的是j结点,但是实际删除的是i。

此外还要考虑的问题是:如果结点不存在怎么办?如果结点是尾结点怎么办?链表只有一个结点?

public classdeleteInode {public static voidmain(String[] args) {

ListNode head= new ListNode(0);

ListNode node1= new ListNode(1);

ListNode node2= new ListNode(2);

ListNode node3= new ListNode(3);

head.setNext(node1);

node1.setNext(node2);

node2.setNext(node3);

delete(head,node2);

printListNode(head);

}public static voiddelete(ListNode head,ListNode target){if(head==null||target==null){return;

}if(head.getNext()==null){if(head==target){

head=null;

}else{return;

}

}if(target.getNext()==null){

ListNode currentNode=head;while(currentNode.getNext()!=null){

currentNode=currentNode.getNext();

}

currentNode.setNext(null);

}if(target.getNext()!=null){

target.setValue(target.getNext().getValue());if(target.getNext().getNext()!=null){

target.setNext(target.getNext().getNext());

}else{

target.setNext(null);

}

}

}public static voidprintListNode(ListNode head){

ListNode current=head;while(current!=null){

System.out.println(current.getValue()+"...");

current=current.getNext();

}

}

}

面试题十五.链表中倒数第K个结点

思路:两个指针A、B,最开始都指向第一个结点,先让A向前走k-1步,然后从第K步开始,A和B同时向前走,这样,当A到达最后一个结点时,B的位置就是倒数第K个结点。

public static ListNode findKNode(ListNode head,intk){if(head==null){

return null; //重要!!!鲁棒性的判断

}

if(k<1){

return null;

}

ListNode firstNode=head;

ListNode secondNode=head;for(int i =0;i

firstNode=firstNode.getNext();

}else{return null;

}

}while(firstNode.getNext()!=null){

firstNode=firstNode.getNext();

secondNode=secondNode.getNext();

}returnsecondNode;

}

相关问题1:求链表的中间结点

解决方法:两个指针,第一个一次走两步,第二个一次走一步,第一个到达终点时,第二个到达中点。

相关问题2:环形链表问题

解决方法:也是两个指针不一样的速度走,如果第一个指针到达终点(getNext()等于空)时都没有碰到第二个,那么就不是环形链表。

注:环形链表可以是首尾相连(O型),也可以是尾部和中间的某个结点相连(6型)。

面试题十六:反转链表

反转链表相当于喊向后转的口号之后,队首变队尾,队尾变队首。

下图说明了存在的一个隐患,那就是当把(i)结点的指针指向h时,这时如果没有提前将(j)结点存储,那么下一步就找不到(j)结点了,链表会断裂。

90238d0f7916b77df31790d315962808.png

所以我们要声明三个变量,分别记录h、i、j,对应上一个、当前、下一个。

public classTest {public static voidmain(String[] args){

ListNode head= new ListNode(0);

ListNode node1= new ListNode(1);

ListNode node2= new ListNode(2);

ListNode node3= new ListNode(3);

head.setNext(node1);

node1.setNext(node2);

node2.setNext(node3);

ListNode node=reverseNode(head);

print(node);

}public staticListNode reverseNode(ListNode head){if(head==null){return null;

}

ListNode preNode= null;

ListNode curNode=head;

ListNode nextNode= null;

ListNode reverseNode= null;while(curNode!=null){

nextNode=curNode.getNext();if(nextNode==null){

reverseNode=curNode;

}

curNode.setNext(preNode);

preNode=curNode;

curNode=nextNode;

}returnreverseNode;

}public static voidprint(ListNode head){

ListNode current=head;while(current!=null){

System.out.println(current.getValue());

current=current.getNext();

}

}

}

面试题十七:合并两个已排序的链表

其实这是一个递归问题,在比较两个链表的头结点后,选定其中一个做为新链表的结点,那么产生下一个结点的过程和最开始一样,两个链表的头结点中选择一个做为新链表的下一个结点,所以是递归问题。

public classTest {public static voidmain(String[] args){

ListNode head1= new ListNode(1);

ListNode node1= new ListNode(3);

ListNode node2= new ListNode(5);

ListNode node3= new ListNode(7);

head1.setNext(node1);

node1.setNext(node2);

node2.setNext(node3);

ListNode head2= new ListNode(2);

ListNode node4= new ListNode(4);

ListNode node5= new ListNode(6);

ListNode node6= new ListNode(8);

head2.setNext(node4);

node4.setNext(node5);

node5.setNext(node6);

ListNode head=merge(head1,head2);

print(head);

}public staticListNode merge(ListNode headA,ListNode headB){

ListNode nodeA=headA;

ListNode nodeB=headB;

ListNode head= null;if(headA==null&&headB!=null){

head=headB;

}if(headB==null&&headA!=null){

head=headA;

}if(headA==null&&headB==null){return null;

}if(nodeA!=null&&nodeB!=null){if(nodeA.getValue()

head=nodeA;

head.setNext(merge(nodeA.getNext(),nodeB));

}else{

head=nodeB;

head.setNext(merge(nodeA,nodeB.getNext()));

}

}returnhead;

}public static voidprint(ListNode head){

ListNode curNode=head;while(curNode!=null){

System.out.println(curNode.getValue());

curNode=curNode.getNext();

}

}

}

面试题十八:树的子结构

两个递归方法,一个是寻找相同的结点,如果遇到相同结点,就调用比较左右子结点的方法。如果根节点和目标结点不相同,就比较左右子结点和目标是否相同,相同,就调用比较子结点方法,不相同,继续调用寻找相同结点方法。

public classTest {public static voidmain(String[] args){

BinaryTreeNode root= new BinaryTreeNode(8);

BinaryTreeNode node1= new BinaryTreeNode(8);

BinaryTreeNode node2= new BinaryTreeNode(7);

BinaryTreeNode node3= new BinaryTreeNode(9);

BinaryTreeNode node4= new BinaryTreeNode(2);

root.setLeft(node1);

root.setRight(node2);

node1.setLeft(node3);

node1.setRight(node4);

BinaryTreeNode target= new BinaryTreeNode(8);

BinaryTreeNode node5= new BinaryTreeNode(9);

BinaryTreeNode node6= new BinaryTreeNode(2);

target.setLeft(node5);

target.setRight(node6);boolean result2 =findSame(root,target);

System.out.println(result2);

}public static booleanfindSame(BinaryTreeNode root,BinaryTreeNode target){boolean result = false;if(root!=null&&target!=null){if(root.getValue()==target.getValue()){

result=sameTree(root,target);

}if(!result){

result=findSame(root.getLeft(),target);

}if(!result){

result=findSame(root.getRight(),target);

}

}returnresult;

}public static booleansameTree(BinaryTreeNode node,BinaryTreeNode target){if(target==null){return true;

}if(node ==null){return false;

}if(node.getValue()!=target.getValue()){return false;

}return sameTree(node.getLeft(),target.getLeft())&&sameTree(node.getRight(),node.getRight());

}

}

面试题十九:二叉树镜像

貌似对于二叉树的整体操作都是递归问题,因为操作过根节点之后,左右两颗子树就可以看成单独的树递归操作。

打印二叉树的时候,每次打印根结点就可以,因为每个结点输出之后,它的子结点都可以看作根结点。

public class Test {

public static void main(String[] args){

BinaryTreeNode root = new BinaryTreeNode(8);

BinaryTreeNode node1 = new BinaryTreeNode(8);

BinaryTreeNode node3 = new BinaryTreeNode(9);

BinaryTreeNode node2 = new BinaryTreeNode(7);

BinaryTreeNode node4 = new BinaryTreeNode(6);

root.setLeft(node1);

root.setRight(node3);

node1.setLeft(node2);

node3.setRight(node4);

mirrorBinary(root);

printBinaryTree(root);

}

public static void mirrorBinary(BinaryTreeNode root){

if(root == null){

return;

}

if(root.getLeft()==null&&root.getRight()==null){

return;

}

BinaryTreeNode temp = root.getLeft();

root.setLeft(root.getRight());

root.setRight(temp);

if(root.getLeft()!=null){

mirrorBinary(root.getLeft());

}

if(root.getRight()!=null){

mirrorBinary(root.getRight());

}

}

public static void printBinaryTree(BinaryTreeNode root){

if(root!=null){

System.out.println(root.getValue());

printBinaryTree(root.getLeft());

printBinaryTree(root.getRight());

}

}

}

按照循环的方法做,就要用到队列了, 利用队列的先进先出的性质,依次添加所有结点,在取出每个结点时,并不对结点操作,而是对结点的两个子结点进行添加进队列和交换的操作。

这里利用队列的方法类似于二叉树的分层遍历所采用的方法。

public static voidmirrorBinary(BinaryTreeNode root){

Queue q = new LinkedList();

BinaryTreeNode temp= new BinaryTreeNode(0);if(root!=null){

q.add(root);

}while(q.size()>0){

BinaryTreeNode node=q.poll();if(node.getLeft()!=null){

q.add(node.getLeft());

}if(node.getRight()!=null){

q.add(node.getRight());

}

temp=node.getLeft();

node.setLeft(node.getRight());

node.setRight(temp);

}

}

面试题二十:顺时针打印矩阵(按圈打印)

public classTest {public static voidmain(String[] args){

BinaryTreeNode root= new BinaryTreeNode(8);int[][] num = {{1,2,3,4},{5,6,7,8,},{1,3,5,7,},{2,4,6,8}};

print(num,4,4);

}public static void print(int[][] num,int rows,intcolumns){if(num==null||rows<=0||columns<=0){return;

}int temp = 0;while(rows>temp*2&&columns>temp*2){

printCircle(num,temp,rows,columns);

temp++;

}

}private static void printCircle(int[][] num,int start,int rows,intcolumns) {int endRow = rows-1-start;int endColumn = columns-1-start;for(int i = start;i<=endColumn;i++){

System.out.print(num[start][i]);

}//如果行数大于起始值,那么肯定不止一行,所以最右一列可以打印

if(start

System.out.print(num[i][endRow]);

}

}//从右到左打印最下一行

if(start=start;i--){

System.out.print(num[endRow][i]);

}

}//打印最左边一列

if(startstart;i--){

System.out.print(num[i][start]);

}

}

System.out.println(".......");

}

}

面试题二十一:包含min函数的栈

创建一个辅助栈,在每次存入新元素时,将新元素和辅助栈的栈顶元素相比,如果栈顶元素小,则再添加一次栈顶元素,否则添加新元素。这样可以保证辅助栈的栈顶始终都是原本栈中的最小元素。

public classminStack {private Stackstack1;private StackstackHelp;private inttemp,pop1,pop2;publicminStack(){

stack1= new Stack();

stackHelp= new Stack();

}public void push(intnum){

stack1.push(num);if(stackHelp.size()==0||num

stackHelp.push(num);

}else{

stackHelp.push(stackHelp.peek());

}

}public voidpop(){

pop1=stack1.pop();

pop2=stackHelp.pop();

System.out.println("本栈是"+pop1+"辅助栈是"+pop2);

}public voidmin(){

System.out.println("最小值是"+stackHelp.pop());

}

}

面试题二十二:栈的压入,弹出序列

输入两组数,判断一个是否是另一个的弹栈顺序。比如A{1,2,3,4,5} B{1,2,5,3,4}  在依次往A中压入元素时,不断比较栈顶元素,1,2,3,当A栈中4进入时,等于B中栈顶元素,那么4弹出。再比较A和B的栈顶元素,都是3,3出栈。然后A是2,B是5,不相同,则5进入A栈,此时栈顶元素相同,5出栈。然后就是2,1.   则第二个数组满足条件。

public classTest {public static voidmain(String[] args){int[] numPush = {1,2,3,4,5};int[] numPop = {4,3,5,2,1};

System.out.println(isPopOrder(numPush,numPop));

}public static boolean isPopOrder(int[] numPush,int[] numPop ){

if(numPush.length<=0||numPop.length<=0||numPush.length!=numPop.length){

return false;

}

Stack stackPop = new Stack();for(int i=numPop.length-1;i>=0;i--){

stackPop.push(numPop[i]);

}

Stack stackPush = new Stack();int j = 0;while(j

stackPush.push(numPush[j]);

j++;

}else{

stackPush.push(numPush[j]);

System.out.println(numPush[j]);while(stackPush.size()>0&&stackPop.size()>0&&stackPush.peek()==stackPop.peek()){

System.out.println("..."+stackPush.pop());

System.out.println(".."+stackPop.pop());

}

j++;

}

}if(stackPush.size()==0){return true;

}else{return false;

}

}

}

面试题二十四:判断一个数组是否是某二叉树的后序遍历顺序

后续遍历结果最后一个是根节点,除去根节点,数组的前半部分应该都比根节点的值小,数组的后半部分应该都比根节点的值大,按照这个规律,递归判断。

int[] left = Arrays.copyOfRange(num, 0, i);          从第0位截取到i-1位。

public static boolean isBinaryTree(int[] num ){if(num.length<=0){return false;

}int root = num[num.length-1];int i = 0;for(;iroot){break;

}

}for(int j =i;j

}

}int[] left = Arrays.copyOfRange(num, 0, i);int[] right = Arrays.copyOfRange(num, i, num.length-1);

Boolean isLeft= true;if(left.length>0){

isBinaryTree(left);

}

Boolean isRight= true;if(right.length>0){

isBinaryTree(right);

}return(isLeft&&isRight);

}

面试题二十五:二叉树中和为某一值的路径

public static voidmain(String[] args){

BinaryTreeNode root= new BinaryTreeNode(5);

BinaryTreeNode node1= new BinaryTreeNode(4);

BinaryTreeNode node2= new BinaryTreeNode(3);

BinaryTreeNode node3= new BinaryTreeNode(5);

BinaryTreeNode node4= new BinaryTreeNode(1);

BinaryTreeNode node5= new BinaryTreeNode(2);

BinaryTreeNode node6= new BinaryTreeNode(1);

root.setLeft(node1);

root.setRight(node3);

node1.setLeft(node2);

node3.setLeft(node4);

node3.setRight(node5);

node4.setLeft(node6);

Stack stack = new Stack();

isPath(12,0,root,stack);

}public static void isPath(int expectSum,int currentSum,BinaryTreeNode root,Stackstack){if(root==null){return;

}

stack.push(root.getValue());

currentSum+=root.getValue();if(root.getLeft()==null&&root.getRight()==null&&currentSum==expectSum){for(Integer e : stack){ //这种方式输出不用谈栈,元素还在栈里

System.out.print(e+"\t");

}

System.out.println();

}if(root.getLeft()!=null){

isPath(expectSum,currentSum,root.getLeft(),stack);

}if(root.getRight()!=null){

isPath(expectSum,currentSum,root.getRight(),stack);

}

stack.pop(); //执行到叶结点(倒数第二层的左子结点)之后,pop,就会回到上一层,然后判断一下有没有右子结点,执行下一步没有的话,再pop,又往上一层,再检查右子结点。

}

面试题二十六:复制一个复杂链表

复杂链表:一个结点可以有两个指向,一个是next,一个是乱序

b31af9899ef04f6c3610b5d478299ccc.png

1.首先只复制next链表,把复制结点放到原本结点的后边。

1941943dd01e1eb7d874c96fbf95def4.png

2.复制乱序指向

61b7e5b77753e87a64c3dbca2015ef50.png

3.分离两个链表,奇数位的连在一起,偶数位的连在一起,就是两个相同的链表。

abe7924c1815c7f64351f98d75b002f5.png

分离时,使用两个指针,一个pNode,一个pCloneNode,将pNode的next指向pClonedNode的next之后,移动pNode到第三个,然后将pCloneNode指向pNode的next,然后移动pCloneNode到第四个,这样不断移动,实现分离。

面试题二十七:二叉搜索树转换成有序双向链表

中序遍历二叉树得到的结果是有序的。

1,curNode记录的是上一个结点,当root行进到最左边叶结点的左子结点时,root为空,程序不执行,退回上一步。上一步的root输入是最左边的叶结点。

2,这时从第5行执行,但这时的curNode为空。第9行:curNode = 最左叶结点。第十行:递归最左子结点的右子结点,如果存在,那么验证是否有左子结点,没有,返回上一层执行第5行,和curNode互指。

3,处理完curNode的子结点,就要返回上一层,这时的root输入为curNode的父结点,执行第5行互指。然后curNode被设置成root。再去寻找root的右子结点。

过程中,由于程序的对于二叉树中结点的遍历顺序是左中右,所以curNode的指向也是这个顺序。在每一次退出上一层时,curNode的指向都会更新。

程序最开始位于左中右的中,然后寻找右,这里的中和右其实都是上一层的左。返回上一层的中,寻找上一层的右。

1 privateBinaryTreeNode curNode ;

2public voidtoTwo(BinaryTreeNode root){

3if(root!=null){

4 toTwo(root.getLeft());

5if(curNode!=null){

6 curNode.setLeft(root);

7 root.setRight(curNode);

8 }

9 curNode=root;

10 toTwo(root.getRight());

}

}

面试题二十八:字符串的排列

和八皇后问题一样,都是用 回溯法解决问题。

public classTest {private final int SET = 1;private final int UNSET = 0;private intsize;private int[] set;private char[] c;private char[] location;private intcount;public Test(int size,char[] c){this.size =size;this.c =c;

location= new char[size];

set= new int[size];

}public void charSet(int i,int j,intk){

location[i]=c[j];if(k==0){

set[j]=UNSET;

}

}public int isPlace(intj){returnset[j];

}public voidprint(){

System.out.println("第"+count+"种方法");for(int j=0;j

System.out.print(location[j]+".");

}

System.out.println();

}public void place(inti){for(int j = 0;j

charSet(i,j,1);

set[j]=SET;if(i

place(i+1);

}else{

count++;

print();

}

charSet(i,j,0);

}

}

}public static voidmain(String[] args){char[] c = {'a'};if(c==null){return;

}else{

Test t= newTest(c.length,c);

t.place(0);

}

}

}

扩展:求字符的所有组合Input:abc  Output:a,b,c,ab,bc,ac,abc

public classTest {public static voidmain(String[] args){

perm("abc");

}public static voidperm(String s){

List result = new ArrayList();for(int i =1;i<=s.length();i++){

perm(s,i,result);

}

}public static void perm(String s,int m,Listresult){if(s.length()

}if(m==0){for(int i =0;i

System.out.println(result.get(i));

}

System.out.println();return;

}else{if(s.length()!=0){

result.add(s.charAt(0)+"");

perm(s.substring(1,s.length()),m-1,result);

result.remove(result.size()-1);

perm(s.substring(1,s.length()),m,result);

}

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值