剑指offer系列题(13-20)

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

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

题目思路

该题有很多的解法,这里提的是一种比较容易想到的思路,及类似于冒泡排序。当前面是为偶数后面是为奇数则交换顺序。当然该题还包括了插入排序,快速、归并等各种方法,在时间复杂度上有优势,为了熟悉常见排序算法,需要去学习一下;
代码
public class Solution {
    public void reOrderArray(int [] array) {
        int temp=0;
        boolean flag=false;
         for(int i=0;i

14.链表中倒数第K个节点

题目描述
输入一个链表,输出该链表中倒数第k个结点。
题目思路
该题采用新建一个List的方式,将链表中的值一次加入到List,因为List也是有序的,故可以计算其下标通过LIst的get方法取的相应位置的值(arr.size()-k).同时需考虑多种情况,k小于等于零时,k大于链表大小时,都需返回null;
代码
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
import java.util.ArrayList;
import java.util.List;
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(k<=0||head==null){
            return null;
        }
           List arr=new ArrayList();
           while(head.next!=null){
               arr.add(head);
               head=head.next;
           }
        arr.add(head);
        return arr.size()>=k?arr.get(arr.size()-k):null;
    }
}



15.反转链表

题目描述
输入一个链表,反转链表后,输出链表的所有元素。
题目思路
该题目本来想着是照上一题的思路,先将其存入一个List里面,而后从后往前依次建立单链表。无奈按此思路写出来不知道是代码错了还是时间超了反正没通过。只能另想他法,通过加入第三变量强行改变链表的指向问题。具体请看代码部分。
代码
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
         if(head==null){
            return null;
        }
        if(head.next==null){
            return head;
        }
        ListNode reverse=null;
        ListNode tmp=null;
        ListNode current=head.next;
        head.next=null;
           while(current.next!=null){
               tmp=current.next;
               current.next=head;
               head=current;
               current=tmp;
           }
        current.next=head;
        reverse=current;
        return reverse;
    }
}
16.合并两个排序链表
题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
题目思路
一开始想到的是插入排序的思想,撸出来后果不其然,复杂过高(因为插排没有考虑其中一个原始链表的有序性),则考虑递归的思路。递归这个东西,好像说不太清,自己看代码。该方法也可非递归实现,核心思路为每次从list1和list2里面取一个元素,因为list1和list2都是有序的,则我们可以从头取至尾。
代码
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1==null){
            return list2;
        }
        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:我们约定空树不是任意一个树的子结构)
题目思路
首先得明白一个事情,则凡是涉及到二叉树的编程一般得用递归的思路。该题目分两步走。 要查找树A中是否存在和树B结构一样的子树, 可以分成两步:
  1. 第一步在树A中找到和B的根节点的值一样的结点R;
  2. 第二步再判断树A中以R为根结点的子树是不是包含和树B一样的结构。
第一步在树A中查找与根结点的值一样的结点,这实际上就是树的遍历。递归调用HasSubTree遍历二叉树A。如果发现某一结点的值和树B的头结点的值相同,则调用DoesTreeHavaTree2,做第二步判断。第二步是判断树A中以R为根结点的子树是不是和树B具有相同的结构。
代码
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        boolean flag=false;
        if(root1!=null&&root2!=null){
            if(root1.val==root2.val){
                flag=Subtree(root1,root2);
            }if(!flag){
            flag=HasSubtree(root1.left,root2)||HasSubtree(root1.right,root2);
            }
           }
        return flag;
    }
    private boolean Subtree(TreeNode root1,TreeNode root2){
        if(root2==null){
            return true;
        }
        if(root1==null){
            return false;
        }
        if(root1.val!=root2.val){
            return false;
        }else{
            return Subtree(root1.left,root2.left)&&Subtree(root1.right,root2.right);
        }
    }
}
18.二叉树镜像
题目描述
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:
题目思路
该题看起来比较复杂,但还是按照老思路。一旦涉及到二叉树的编程,一定要想到递归的思路。递归的调换左右孩子的即可。
代码
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public void Mirror(TreeNode root) {
        if(root==null) return;
        TreeNode temp=null;
        if(root.left!=null||root.right!=null){
            temp=root.left;
            root.left=root.right;
            root.right=temp;
        }
        if(root.left!=null){
            Mirror(root.left);
        }
        if(root.right!=null){
            
            Mirror(root.right);
        }
    }
}

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.
题目思路
该题目确实比较费劲,先按自己暴力思路撸了会代码,发现太复杂了。然后放弃了,想去看别人的代码,发现也挺复杂的。于是决定继续撸自己的代码,意外的是还真成了。第一种情况:行列都为偶数,先打印一行(行不变列累加),打印一列(起始行加1,列不变,行累加),行不变列递减(行为最后一行,列为最后一列),列不变行递减。但每走一圈它的边界条件也在边,所以需设置四个变量作为边界条件。第二种行为奇数或列为奇数或两个都为奇数。这个时候会出现在最后的时候只打印一行或一列或一个数。具体请看代码。
代码
import java.util.ArrayList;
public class Solution {
    public  ArrayList al=null;
    public ArrayList printMatrix(int [][] matrix) {
        al=new ArrayList();
       int wide=matrix[0].length;
       int high=matrix.length;
       if(wide<=high){
          int n=wide/2;
           huatu(n,wide,high,matrix);
       if(wide%2==1){
       for(int i=n;ibb;b--){
               al.add(matrix[a][b]);
           }for(int a=ba,b=bb;a>aa;a--){
               al.add(matrix[a][b]);
           }
          aa++;
          bb++;
          ab--;
          ba--;
       }
    }
}
20.包含min函数的栈
题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
题目思路
该题目是对栈知识的考查,及出栈入栈、栈顶元素、判空、栈的扩容(数组的扩容)等。栈其实就是一个受限制的数组或者链表。这里有个关键的细节就是引进了一个系统栈来保存最小值。因为最小值会受出栈入栈的影响,所以用一个对应的辅助栈可以降低时间复杂度。具体妙处可以看代码体会。
代码
import java.util.Stack;
import java.util.Arrays;
public class Solution {
    private int size=0;
    private int min=Integer.MAX_VALUE;
    private Stack minStack=new Stack();
    private Integer[] elements=new Integer[10];
    public void push(int node) {
        ensureCapacity(size+1);
        elements[size++]=node;
        if(node <= min){
            minStack.push(node);
            min = minStack.peek();
        }else{
            minStack.push(min);
        }
    }
    private void ensureCapacity(int size){
        int len=elements.length;
        if(size>len){
            int newlen=(len*3)/2+1;
            elements = Arrays.copyOf(elements,newlen);
        }
    }
    public void pop() {
        Integer top=top();
         if(top != null){
            elements[size-1] = (Integer) null;
        }
        size--;
        minStack.pop();
        min=minStack.peek();
    }
    
    public int top() {
        if(!empty()){
            if(size-1>=1) return elements[size-1];
        }
        return (Integer)null;
    }
    public boolean empty(){
        return size==0;
    }
    public int min() {
        return min;
    }
}

你可能感兴趣的:(算法练习,树,链表,栈,算法,面试)