剑指offer题目实现21~30(java实现)

面试题21:调整数组顺序使奇数位于偶数前面

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型一维数组 
     * @return int整型一维数组
     */
    public int[] reOrderArray (int[] array) {
        // write code here
        int left = 0;
        int right = array.length - 1;
        int temp = 0;

        while(left < right){
            if(array[left] % 2 == 0){
                if(array[right] % 2 == 1){
                    temp = array[left];
                    array[left] = array[right];
                    array[right] = temp;
                    left++;
                    right--;
                }else{
                    right--;
                }
            }else {
                left++;
            }
        }

        return array;
    }
}

import java.util.*;
public class Solution {
    public int[] reOrderArray (int[] array) {
        int n = array.length;
        int[] res = new int[n];
        //统计奇数个数
        int odd = 0; 
        //遍历统计
        for(int i = 0; i < n; i++){ 
            if(array[i] % 2 == 1)
                odd++;
        }
        //x与y分别表示答案中奇偶数的坐标
        int x = 0, y = odd; 
        for(int i = 0; i < n; i++){
            //奇数在前
            if(array[i] % 2 == 1){ 
                res[x] = array[i];
                x++;
            //偶数在后
            }else{ 
                res[y] = array[i];
                y++;
            }
        }
        return res;
    }
}

面试题22:链表中倒数第k个节点

//自己写的
import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param pHead ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    public ListNode FindKthToTail (ListNode pHead, int k) {
        // write code here
        int count = 0;
        ListNode originPhead = pHead;

        while(pHead != null){
            pHead = pHead.next;
            count++;
        }
        if(count < k){
            pHead = null;
            return pHead;
        }

        int index = count - k + 1;

        count = 1;
        while(count < index){
            originPhead = originPhead.next;
            count++;
        }

        return originPhead;
    }
}
//标准答案
import java.util.*;
public class Solution {
    public ListNode FindKthToTail (ListNode pHead, int k) {
        int n = 0;
        ListNode p = pHead;
         //遍历链表,统计链表长度
        while(p != null){
            n++;
            p = p.next;
        }
        //长度过小,返回空链表
        if(n < k) 
            return null;
        p = pHead;
        //遍历n-k次
        for(int i = 0; i < n - k; i++) 
            p = p.next;
        return p;
    }
}
import java.util.*;
public class Solution {
    public ListNode FindKthToTail (ListNode pHead, int k) {
        int n = 0;
        ListNode fast = pHead; 
        ListNode slow = pHead;
        //快指针先行k步
        for(int i = 0; i < k; i++){  
            if(fast != null)
                fast = fast.next;
            //达不到k步说明链表过短,没有倒数k
            else 
                return slow = null;
        }
        //快慢指针同步,快指针先到底,慢指针指向倒数第k个
        while(fast != null){ 
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}
    public Node middleNode(){
        //当fast的速度是slow速度的两倍时,当fast走到最后一个节点时,slow出于中间位置。
        Node fast=head;
        Node slow=head;
        while(fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
       return slow;
    }

面试题23:链表中环的入口节点

public class Solution {
    //判断有没有环,返回相遇的地方
    public ListNode hasCycle(ListNode head) {
        //先判断链表为空的情况
        if(head == null) 
            return null;
        //快慢双指针
        ListNode fast = head; 
        ListNode slow = head;
        //如果没环快指针会先到链表尾
        while(fast != null && fast.next != null){ 
            //快指针移动两步
            fast = fast.next.next; 
            //慢指针移动一步
            slow = slow.next; 
            //相遇则有环,返回相遇的位置
            if(fast == slow) 
                return slow;
        }
        //到末尾说明没有环,返回null
        return null; 
    }
public class Solution {
    //判断有没有环,返回相遇的地方
    public ListNode hasCycle(ListNode head) {
        //先判断链表为空的情况
        if(head == null) 
            return null;
        //快慢双指针
        ListNode fast = head; 
        ListNode slow = head;
        //如果没环快指针会先到链表尾
        while(fast != null && fast.next != null){ 
            //快指针移动两步
            fast = fast.next.next; 
            //慢指针移动一步
            slow = slow.next; 
            //相遇则有环,返回相遇的位置
            if(fast == slow) 
                return slow;
        }
        //到末尾说明没有环,返回null
        return null; 
    }
    
    public ListNode EntryNodeOfLoop(ListNode pHead) {
        ListNode slow = hasCycle(pHead);
        //没有环
        if(slow == null) 
            return null;
        //快指针回到表头
        ListNode fast = pHead; 
        //再次相遇即是环入口
        while(fast != slow){ 
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

再次相遇的地方就是环的入口

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if(pHead == null){
            return null;
        }
        // 1.判断链表中有环
        ListNode l=pHead,r=pHead;
        boolean flag = false;
        while(r != null && r.next!=null){
            l=l.next;
            r=r.next.next;
            if(l==r){
                flag=true;
                break;
            }
        }
        if(!flag){
            return null;
        }else{
            // 2.得到环中节点的数目
            int n=1;
            r=r.next;
            while(l!=r){
                r=r.next;
                n++;
            }
            // 3.找到环中的入口节点
            //先让一个指针走环的长度,然后两个相遇的地方就是环的入口
            l=r=pHead;
            for(int i=0;i<n;i++){
                r=r.next;
            }
            while(l!=r){
                l=l.next;
                r=r.next;
            }
            return l;
        }
    }
}

面试题24:反转链表

最开始使用单链表无法解决

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
import java.util.Stack;
public class Solution {
    public ListNode ReverseList(ListNode head) {
        Stack<ListNode> stack= new Stack<>();
        //把链表节点全部摘掉放到栈中
        while (head != null) {
            stack.push(head);
            head = head.next;
        }
        if (stack.isEmpty())
            return null;
        ListNode node = stack.pop();
        ListNode dummy = node;
        //栈中的结点全部出栈,然后重新连成一个新的链表
        while (!stack.isEmpty()) {
            ListNode tempNode = stack.pop();
            node.next = tempNode;
            node = node.next;
        }
        //最后一个结点就是反转前的头结点,一定要让他的next等于空,否则会构成环
        node.next = null;
        return dummy;
    }
}

时间复杂度:O(n),空间复杂度:O(n)

public ListNode ReverseList(ListNode head) {
    //新链表
    ListNode newHead = null;
    while (head != null) {
        //先保存访问的节点的下一个节点,保存起来
        //留着下一步访问的
        ListNode temp = head.next;
        //每次访问的原链表节点都会成为新链表的头结点,
        //其实就是把新链表挂到访问的原链表节点的
        //后面就行了
        head.next = newHead;
        //更新新链表
        newHead = head;
        //重新赋值,继续访问
        head = temp;
    }
    //返回新链表
    return newHead;
}

public ListNode reverseList(参数0) {
    if (终止条件)
        return;

    逻辑处理(可能有,也可能没有,具体问题具体分析)

    //递归调用
    ListNode reverse = reverseList(参数1);

    逻辑处理(可能有,也可能没有,具体问题具体分析)
}
if (head == null || head.next == null)
    return head;
public ListNode ReverseList(ListNode head) {
    //终止条件
    if (head == null || head.next == null)
        return head;
    //保存当前节点的下一个结点
    ListNode next = head.next;
    //从当前节点的下一个结点开始递归调用
    ListNode reverse = ReverseList(next);
    //reverse是反转之后的链表,因为函数reverseList
    // 表示的是对链表的反转,所以反转完之后next肯定
    // 是链表reverse的尾结点,然后我们再把当前节点
    //head挂到next节点的后面就完成了链表的反转。
    next.next = head;
    //这里head相当于变成了尾结点,尾结点都是为空的,
    //否则会构成环
    head.next = null;
    return reverse;
}
public ListNode ReverseList(ListNode head) {
    if (head == null || head.next == null)
        return head;
    ListNode reverse = ReverseList(head.next);
    head.next.next = head;
    head.next = null;
    return reverse;
}
public ListNode ReverseList(ListNode head) {
    return reverseListInt(head, null);
}

private ListNode reverseListInt(ListNode head, ListNode newHead) {
    if (head == null)
        return newHead;
    ListNode next = head.next;
    head.next = newHead;
    return reverseListInt(next, head);
}
public ListNode ReverseList(ListNode head) {
    return reverseListInt(head, null);
}

private ListNode reverseListInt(ListNode head, ListNode newHead) {
    if (head == null)
        return newHead;
    ListNode next = head.next;
    head.next = newHead;
    ListNode node = reverseListInt(next, head);
    return node;
}

面试题25:合并两个排序的链表

/*
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;
        }
        else if(list2==null){
            return list1;
        }
        if(list2.val>list1.val){
            list1.next = Merge(list1.next,list2);
            return list1;
        }
        else{
            list2.next = Merge(list1,list2.next);
            return list2;
        }
    }
}
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        ListNode dummy = new ListNode(-1);
        ListNode res = dummy;
        // 必须保证两个list都不为空
        while(list1 != null & list2 != null) {
            if(list1.val > list2.val) {
                dummy.next = list2;
                list2 = list2.next;
                dummy = dummy.next;
            } else if(list1.val <= list2.val) {
                dummy.next = list1;
                list1 = list1.next;
                dummy = dummy.next;
            }
        }
        // list1后面还有,就把剩下的全部拿走
        if(list1 != null) {
            dummy.next = list1;
        }
        if(list2 != null) {
            dummy.next = list2;
        }
        //因为最后的到的链表要返回出去,所以空间复杂度为O(1)
        return res.next;
    }
}

面试题26:树的字结构

树一般要注意递归思想的应用

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

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

    }
}
*/

/*思路:参考剑指offer
1、首先设置标志位result = false,因为一旦匹配成功result就设为true,
剩下的代码不会执行,如果匹配不成功,默认返回false
2、递归思想,如果根节点相同则递归调用DoesTree1HaveTree2(),
如果根节点不相同,则判断tree1的左子树和tree2是否相同,
再判断右子树和tree2是否相同
3、注意null的条件,HasSubTree中,如果两棵树都不为空才进行判断,
DoesTree1HasTree2中,如果Tree2为空,则说明第二棵树遍历完了,即匹配成功,
tree1为空有两种情况(1)如果tree1为空&&tree2不为空说明不匹配,
(2)如果tree1为空,tree2为空,说明匹配。
*/

public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        boolean result = false;
            if(root1 != null && root2 != null){
                if(root1.val == root2.val){
                    result = DoesTree1HaveTree2(root1,root2);
                }
                if(!result){result = HasSubtree(root1.left, root2);}
                if(!result){result = HasSubtree(root1.right, root2);}
            }
            return result;
    }
    public boolean DoesTree1HaveTree2(TreeNode root1,TreeNode root2){
            if(root1 == null && root2 != null) return false;
            if(root2 == null) return true;
            if(root1.val != root2.val) return false;
            return DoesTree1HaveTree2(root1.left, root2.left) 
                    && DoesTree1HaveTree2(root1.right, root2.right);
        }
}
if(!root) 
    return true/false;
if(!root->left) 
    return true/false/递归函数;
if(!root->right) 
    return true/false/递归函数;

面试题27:二叉树的镜像

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

import java.util.*;
public class Solution {
    public TreeNode Mirror (TreeNode pRoot) {
        //空树返回
        if(pRoot == null) 
            return null;
        //先递归子树
        TreeNode left = Mirror(pRoot.left);  
        TreeNode right = Mirror(pRoot.right);
        //交换
        pRoot.left = right; 
        pRoot.right = left;
        return pRoot;
    }
}
import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

import java.util.*;
public class Solution {
    public TreeNode Mirror (TreeNode pRoot) {
        //空树
        if(pRoot == null)  
            return null;
        //辅助栈
        Stack<TreeNode> s = new Stack<TreeNode>(); 
        //根节点先进栈
        s.push(pRoot); 
        while (!s.isEmpty()){ 
            TreeNode node = s.pop();
            //左右节点入栈
            if(node.left != null) 
                s.push(node.left);
            if(node.right != null) 
                s.push(node.right);
            //交换左右
            TreeNode temp = node.left; 
            node.left = node.right;
            node.right = temp;
        }
        return pRoot;
    }
}

面试题28:对称的二叉树

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }
}
*/

public class Solution {
    boolean recursion(TreeNode root1, TreeNode root2){
        //可以两个都为空
        if(root1 == null && root2 == null) 
            return true;
        //只有一个为空或者节点值不同,必定不对称
        if(root1 == null || root2 == null || root1.val != root2.val) 
            return false;
        //每层对应的节点进入递归比较
        return recursion(root1.left, root2.right) 
                && recursion(root1.right, root2.left);
    }
    boolean isSymmetrical(TreeNode pRoot) {
        return recursion(pRoot, pRoot);
    }
}
//从左往右加入队列
q1.offer(left.left); 
q1.offer(left.right);
//从右往左加入队列
q2.offer(right.right); 
q2.offer(right.left);
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

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

    }

}
*/
import java.util.*;
public class Solution {
    boolean isSymmetrical(TreeNode pRoot) {
        //空树为对称的
        if(pRoot == null) 
            return true;
        //辅助队列用于从两边层次遍历
        Queue<TreeNode> q1 = new LinkedList<TreeNode>(); 
        Queue<TreeNode> q2 = new LinkedList<TreeNode>();
        q1.offer(pRoot.left);
        q2.offer(pRoot.right);
        while(!q1.isEmpty() && !q2.isEmpty()){ 
            //分别从左边和右边弹出节点
            TreeNode left = q1.poll(); 
            TreeNode right = q2.poll();
            //都为空暂时对称
            if(left == null && right == null)
                continue;
            //某一个为空或者数字不相等则不对称
            if(left == null || right == null || left.val != right.val)
                return false;
            //从左往右加入队列
            q1.offer(left.left); 
            q1.offer(left.right);
            //从右往左加入队列
            q2.offer(right.right); 
            q2.offer(right.left);
        }
        //都检验完都是对称的
        return true;
    }
}

面试题29:顺时针打印矩阵

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> res = new ArrayList<>();
         //先排除特殊情况
        if(matrix.length == 0) {
            return res;
        }
        //左边界
        int left = 0; 
        //右边界
        int right = matrix[0].length - 1; 
        //上边界
        int up = 0; 
        //下边界
        int down = matrix.length - 1; 
        //直到边界重合
        while(left <= right && up <= down){ 
            //上边界的从左到右
            for(int i = left; i <= right; i++) 
                res.add(matrix[up][i]); 
            //上边界向下
            up++; 
            if(up > down)
                break;
            //右边界的从上到下
            for(int i = up; i <= down; i++) 
                res.add(matrix[i][right]);
            //右边界向左
            right--; 
            if(left > right)
                break;
            //下边界的从右到左
            for(int i = right; i >= left; i--) 
                res.add(matrix[down][i]);
            //下边界向上
            down--; 
            if(up > down)
                break; 
            //左边界的从下到上
            for(int i = down; i >= up; i--) 
                res.add(matrix[i][left]);
            //左边界向右
            left++; 
            if(left > right)
                break;
        }
        return res;
    }
}

面试题30:包含min函数的栈

//最开始的写法,时间复杂度 O(n) 空间复杂度 O(n),不满足要求
import java.util.Stack;

public class Solution {
    Stack minStack = new Stack();
    
    public void push(int node) {
        minStack.push(node);
    }
    
    public void pop() {
        minStack.pop();
    }
    
    public int top() {
        return (int)minStack.get(0);
    }
    
    public int min() {
        int[] arr = new int[100];
        int min = -10001;
        while(!minStack.empty()){
            if(min > (int)minStack.pop()){
                min = (int)minStack.pop();
            }
        }

        return min;
    }
}
//空或者新元素较小,则入栈
if(s2.isEmpty() || s2.peek() > node)  
    s2.push(node);
else
    //重复加入栈顶
    s2.push(s2.peek());
import java.util.Stack;

public class Solution {
    //用于栈的push 与 pop
    Stack<Integer> s1 = new Stack<Integer>(); 
    //用于存储最小min
    Stack<Integer> s2 = new Stack<Integer>(); 
    public void push(int node) {
        s1.push(node);  
        //空或者新元素较小,则入栈
        if(s2.isEmpty() || s2.peek() > node)  
            s2.push(node);
        else
            //重复加入栈顶
            s2.push(s2.peek());  
    }
    
    public void pop() {
        s1.pop();
        s2.pop();
    }
    
    public int top() {
        return s1.peek();
    }
    
    public int min() {
        return s2.peek();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值