剑指Offer算法题JAVA版13-20题(全是个人写的非官方,只供参考和自己复习,测试用例都通过了。)

13.调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

(思路:是一个类似与快速排序,的思路,但快速排序是不稳定的。要保证,偶数和基数的相对位置稳定)

 public void reOrderArray(int [] array) {
		        int n=0;//指向要被交换的位置,始终位于偶数串的第一位
		        int k=0;//记录连续的偶数串长度
		        for(int i=0;i<array.length;i++){//其中i就是遍历整个数组,走到偶数,就继续往前走,并记录走过偶数的个数,遇到奇数就将该基数,放到n所在位置,然后将整个偶数串后移一位。
		        	if((array[i]&1)==0){//计算遍历到i位置,一共有多少个偶数
		        		k++;//
		        	}
		        	if((array[i]&1)==1){//当为级数
		        			int t=array[i];
		        			int p=k;
		        			while(p>0){//偶数串总体移动,保持相对位置不变
		        				array[n+p]=array[n+p-1];//整个偶数串,向后移。
		        				p--;
		        			}
		        			array[n]=t;//把奇数和需要被交换的位置
		        			n++;//被交换位置向前移动。
		        		}
		    }
		  }


14. 链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点。

(思路很简单,两个指针都指向头节点,然后让其中一个向前跑k-1次,然后,后边的指针开始跟着跑,直到前面指针的next 是空,则后面指针的位置就是倒数第k个元素)

 public ListNode FindKthToTail(ListNode head,int k) {
			 ListNode p=head;//后起步的指针
			 ListNode pre=head;//先起步的指针
			if(k<=0)return null;//非法的k
			while(k>1&&pre!=null){//让pre先走k-1步,
				pre=pre.next;
					k--;
			}
			if(pre==null){//整个链不足k个,返回空
				return null;
			}else{
			while(pre.next!=null){//pre走k-1之后,p和pre一起走。
				pre=pre.next;
				p=p.next;
			}
			return p;
			}
		    
		 }

15. 反转链表

输入一个链表,反转链表后,输出链表的所有元素。

15.1(思路:将整个链放入一个栈,放完之后,出栈,然后根据出栈的顺序重新连接一条链就好了)

 public ListNode ReverseList(ListNode head) {
			 	Stack<ListNode> stack=new Stack<ListNode>();
			 	while(head!=null){//全部放入栈
			 		stack.push(head);
			 		head=head.next;
			 	}
			 	if(!stack.isEmpty()){//栈不为空的情况下
			 		ListNode last=stack.pop();//last指针指向第一个出<span style="line-height: 25.2px; font-family: arial, STHeiti, 'Microsoft YaHei', 宋体;">栈</span>的元素
			 		ListNode first=last;//新的first指针也指向第一个出栈的元素
			 		while(!stack.isEmpty()){
			 			last.next=stack.pop();//last的下一个元素等于下一个弹出的元素
			 			last=last.next;//last指针指向最新的弹出的元素
			 		}
			 		last.next=null;//循环之后,last位于最后一个元素,将最后一个元素的next置为空。
			 		return first;//返回新链表的头
			 	}else{//栈为空,返回空
			 		return null;
			 	}
		    }

15.2用三个指针来,来操作,这样节省空间。

 public ListNode ReverseList(ListNode head) {
			 	ListNode pre=null;
			 	ListNode hnext=null;
			 	while(head!=null){
			 		hnext=head.next;
			 		head.next=pre;
			 		pre=head;
			 		head=hnext;
			 	}
			 	return pre;
		    }

16.合并两个排序的链表

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

16.1非递归方法

(思路:思路较简单)

 public ListNode Merge(ListNode list1,ListNode list2) {
         ListNode list3=null;
	   ListNode listHead=null;
	   if(list1!=null&list2!=null){
	   if(list1.val<=list2.val){//将返回链表的头指针放在两个链表中值小的头上。
		   list3=new ListNode(list1.val);
		   listHead=list3;
		   list1=list1.next;
		   
	   }else if(list2.val<list1.val){
		   list3=new ListNode(list2.val);
		   listHead=list3;
		   list2=list2.next;
	   }
	   //一次循环,两个链表元素一次比较,值较小的接到,返回链表后面,知道其中一个链表走完
	   while(list1!=null&&list2!=null){
		   if(list1.val<=list2.val){
			   list3.next=list1;
			   list3=list3.next;
			   list1=list1.next;
		   }else{
			   list3.next=list2;
			   list3=list3.next;
			   list2=list2.next;
		   }
		  
	   }
	   if(list1==null){//将没有遍历完的链表的剩余部分接到,返回链表的后面
		   list3.next=list2;
	   }else if(list2==null){
		   list3.next=list1;
	   }
	   return listHead;
	   }else if(list1==null&&list2!=null){
		  listHead=list2;
	   }else if(list2==null&&list1!=null){
		   listHead=list1;
	   }
	  return listHead;
    }
16.2递归的方法

 public ListNode Merge(ListNode list1,ListNode list2) {
			 if(list1==null){
				 return list2;
			 }else if(list2==null){
				 return list1;
			 }
		        if(list1.val<=list2.val){
		        	 list1.next=Merge(list1.next,list2);
		        	 return list1;
		        }else{
		        	 list2.next=Merge(list1,list2.next);
		        	 return list2;
		        }
		    }

17.树的子结构

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

public boolean HasSubtree(TreeNode root1,TreeNode root2) {
			 if(root1==null||root2==null){
				 return false;
			 }
			if(root1.val==root2.val){//一旦当前节点相同,便调用<pre name="code" class="java" style="color: rgb(51, 51, 51); font-size: 14px; line-height: 22.4px;">isChildTree()方法,查看root2是否是root1的子树
boolean result=Solution.isChildTree(root1, root2);if(!result){
boolean res1=HasSubtree(root1.right,root2);boolean res2=HasSubtree(root1.left, root2);return res2||res1;}else{return true;}}else{boolean res1=HasSubtree(root1.right,root2);boolean res2=HasSubtree(root1.left, root2);return res2||res1;} } public static boolean isChildTree(TreeNode root1,TreeNode root2){// 该方法用来判断 两个相同根的树,root2是否是root1的子树 boolean result=false; if(root2==null){ return true; }else if(root1==null){ return false; } if(root1.val!=root2.val){ return false; }else{boolean res1= isChildTree(root1.right,root2.right);boolean re2=isChildTree(root1.left, root2.left);result=res1&&re2;return result; } }

 18. 
二叉树的镜像 

操作给定的二叉树,将其变换为源二叉树的镜像。 
输入描述:
二叉树的镜像定义:源二叉树 
    	    8
    	   /  \
    	  6   10
    	 / \  / \
    	5  7 9 11
    	镜像二叉树
    	    8
    	   /  \
    	  10   6
    	 / \  / \
    	11 9 7  5
 public void Mirror(TreeNode root) {
			 	if(root!=null){
			 		Mirror(root.left);
			 		Mirror(root.right);
			 		TreeNode temp=root.left;
			 		root.left=root.right;
			 		root.right=temp;
			 	}
		        	
		        
		    }

19.顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

	public ArrayList<Integer> printMatrix(int [][] matrix) {
			ArrayList<Integer> list=new ArrayList<Integer>();
		       if(matrix.length==0){
		    	   return null;
		       }else if(matrix.length==1){
		    	  for(int j=0;j<matrix[0].length;j++){
		    		  list.add(matrix[0][j]);
		    	  }
		       }else if(matrix[0].length==1){
		    	   for(int i=0;i<matrix.length;i++){
		    		   list.add(matrix[i][0]);
		    	   }
		       }else{
		    	   int k=matrix.length<=matrix[0].length?matrix.length:matrix[0].length;
		    	   double t=((double)k)/2;
		    	   int x=0;
		    	   while(t>0){
		    		   if(k-x*2>1){
		    		for(int i=x;i<matrix[0].length-x-1;i++){
		    			list.add(matrix[x][i]);
		    		}
		    		for(int i=x;i<matrix.length-x-1;i++){
		    			list.add(matrix[i][matrix[0].length-x-1]);
		    		}
		    		for(int i=matrix[0].length-x-1;i>x;i--){
		    			list.add(matrix[matrix.length-x-1][i]);
		    		}
		    		for(int i=matrix.length-x-1;i>x;i--){
		    			list.add(matrix[i][x]);
		    		}
		    		x++;
		    		t--;
		    		   }else{
		    			   if(matrix.length>=matrix[0].length){
		    				   for(int i=x;i<matrix.length-x;i++){
		    					   list.add(matrix[i][x]);
		    				   }
		    				
		    			   }else{
		    				   for(int i=x;i<matrix[0].length-x;i++){
		    					   list.add(matrix[x][i]);
		    				   }
		    				
		    			   }
		    			   x++;
		   		    		t--;
		    		   }
		    	   }

		    	  
		       }
		       return list;
	    }
		


20.包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

(思路:一个min栈用来存储当前最小的数,该栈栈顶始终是当前最小。出栈操作的时候,判断当前最小元素被弹出,若当前最小弹出,那么min栈也弹出,此时当前最小,依旧是min栈的栈顶)

public class Solution {
		  Stack<Integer> stack=new Stack<Integer>();
		  Stack<Integer> min =new Stack<Integer>();
	    public void push(int node) {
	    	int minn=Integer.MAX_VALUE;
	    	if(!min.isEmpty()){
	    		minn=min.peek();
	    	}
	        stack.push(node);
	        if(node<=minn){
	        	minn=node;
	        	min.push(node);
	        }
	       
	    }
	    public void pop() {
	      int i=stack.pop();
	      if(i==min.peek()){
	    	  min.pop();
	      }
	      
	    }
	    
	    public int top() {
	        return  stack.peek();
	    }
	    
	    public int min() {
	      return min.peek();
	      
	    }
		
			
		}
	




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值