11天刷完《剑指Offer》/ Day2:第11~20题

part1

文章目录

  • part1
  • part2
    • T11 二进制中1的个数
    • T12 数值的整数次方
    • T13. 调整数组顺序使奇数位于偶数前面
    • T14. 链表中倒数第 K 个结点
    • T15. 反转链表
    • T16. 合并两个排序的链表!
    • T17. 树的子结构!
    • T18. 二叉树的镜像
    • T19. 顺时针打印矩阵!
    • T20. 包含 min 函数的栈!

part2

T11 二进制中1的个数

  • 题目描述

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

  • 解题思路
public class Solution {
    public int NumberOf1(int n) {
        int count=0;
        while(n!=0){
            count++;
            n=n&(n-1);
        }
        //把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.
        那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
        return count;

    }
}

T12 数值的整数次方

  • 题目描述

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

保证base和exponent不同时为0

  • 解题思路
public class Solution {
    public double Power(double base, int exponent) {
        double res=1.0;
        int e=exponent>0?exponent:-exponent;
        for(int i=0;i < e;i++){
            res =res* base;
         }
        return exponent>0 ? res : 1/res;
  }
}

1、开始没考虑res的double问题,用int,导致结果报错;
2、没考虑指数为负数,返回1,错了

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

  • 题目描述

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

  • 解题思路

1.插入排序

public static void insertSort(int[] arr, int start, int end) {
        for (int i = 1; i < arr.length; i++) {
            int value = arr[i];
            int cur = i;
            while (cur > 0 && value < arr[cur - 1]) {
                arr[cur] = arr[cur - 1];
                cur--;
            }
            arr[cur] = value;
        }
    }

2.快排

这道题就是将数组分为奇数部分和偶数部分,每遍历到一个奇数,就迭代地将其放入前面奇数部分,每遍历到一个偶数,就继续遍历。相当于任意奇数都小于任意偶数,所有奇数都相等,所有偶数都相等,然后使用快速排序排序数组。

public void reOrderArray(int [] array) {
        if (array == null || array.length < 2) {
            return;
        }
        int n = array.length;
        for (int i = 1; i < n; i++) {
            // 当前元素是奇数,就移动到奇数序列
            if (array[i] % 2 != 0) {
                int value = array[i];
                int cur = i;
                while (cur > 0 && (array[cur - 1] % 2 == 0)) {
                    array[cur] = array[cur - 1];
                    cur--;
                }
                array[cur] = value;
            }
            // 当前元素是偶数,无须移动
        }
    }

错误的:
原因?

这里是引用

public class Solution {
    public void reOrderArray(int [] array) {
          ArrayList<> al = new ArrayList<>();
        for(int i=0;i<array.size();i++){
            if(array[i]%2!=0){
                al.Add(array[i]);
            }
        }
         for(int j=0;j<array.size();j++){
            if(array[j]%2==0){
                al.Add(array[j]);
            }
        }
       Object[] objectArray  = al.toArray();
         return objectArray;
    }
}

T14. 链表中倒数第 K 个结点

  • 题目描述

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

  • 解题思路
    快慢算法
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
		 if(head == null || k ==0 ){
		            return null;
		        }
		        ListNode slow=head;
		        ListNode fast=head;
		        //都从头结点开始
		        for(int i=0;i<k;i++){
		            if(fast==null){
		                return null;
		            }
		            fast=fast.next;
		 
		        }//相同的路程,fast先走k步
		        while(fast!=null){
		            slow=slow.next;
		            fast=fast.next;
		        }//slow跟着fast走剩下路程,即停在倒数第k点
		 
		        return slow;
 
    }
}

T15. 反转链表

  • 题目描述

输入一个链表,反转链表后,输出新链表的表头。

  • 解题思路
    头插法,需要一个新链表的节点和一个往后移动的替换节点
public class Solution {
    public ListNode ReverseList(ListNode head) {
      ListNode cur=null;//为甚么不是=head?
         if(head == null || head.next == null){
            return head;
        }
        //首先排除空表!要考虑周全,老忘记!
      while(head!=null){
          ListNode t=head.next;
          head.next=cur;
          cur=head;
          head=t;
          
      }

T16. 合并两个排序的链表!

  • 题目描述

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

  • 解题思路

1.递归

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;
       }       
    }
}

2.非递归:学习!

if(list1 == null){
            return list2;
        }
        if(list2 == null){
            return list1;
        }
        ListNode mergeHead = null;
        ListNode current = null;     
        while(list1!=null && list2!=null){
            if(list1.val <= list2.val){
                if(mergeHead == null){
                   mergeHead = current = list1;
                }else{
                   current.next = list1;
                   current = current.next;
                }
                list1 = list1.next;
            }else{
                if(mergeHead == null){
                   mergeHead = current = list2;
                }else{
                   current.next = list2;
                   current = current.next;
                }
                list2 = list2.next;
            }
        }
        if(list1 == null){
            current.next = list2;
        }else{
            current.next = list1;
        }
        return mergeHead;

T17. 树的子结构!

  • 题目描述

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

  • 解题思路???
public class Solution {
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root1 == null || root2 == null) {
            return false;
        }
        return judgeSubTree(root1, root2) ||
               judgeSubTree(root1.left, root2) ||
               judgeSubTree(root1.right, root2);
    }
 
    private boolean judgeSubTree(TreeNode root1, TreeNode root2) {
        if (root2 == null) {
            return true;
        }
        if (root1 == null) {
            return false;
        }
        if (root1.val != root2.val) {
            return judgeSubTree(root1.left, root2) ||
                   judgeSubTree(root1.right, root2);
        }
        return judgeSubTree(root1.left, root2.left) &&
               judgeSubTree(root1.right, root2.right);
    }
}

T18. 二叉树的镜像

  • 题目描述

操作给定的二叉树,将其变换为源二叉树的镜像。

  • 解题思路
    交换左右节点,递归调用该方法
public class Solution {
    public void Mirror(TreeNode root) {
        if(root == null){
            return;//返回空!
        }
        TreeNode tem = root.left;
        root.left = root.right;
        root.right = tem;
        Mirror(root.left);
        Mirror(root.right);
    }
}

T19. 顺时针打印矩阵!

  • 题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 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.

  • 解题思路

刷 LeetCode 看到的大神题解,感觉容易理解且好写
简单来说,就是不断地收缩矩阵的边界
定义四个变量代表范围,up、down、left、right

1、向右走存入整行的值,当存入后,该行再也不会被遍历,代表上边界的 up 加一,同时判断是否和代表下边界的 down 交错
2、向下走存入整列的值,当存入后,该列再也不会被遍历,代表右边界的 right 减一,同时判断是否和代表左边界的 left 交错
3、向左走存入整行的值,当存入后,该行再也不会被遍历,代表下边界的 down 减一,同时判断是否和代表上边界的 up 交错
4、向上走存入整列的值,当存入后,该列再也不会被遍历,代表左边界的 left 加一,同时判断是否和代表右边界的 right 交错
时间复杂度:o(n)

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> list = new ArrayList<>();
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
            return list;
        }
        int up = 0;
        int down = matrix.length-1;
        int left = 0;
        int right = matrix[0].length-1;
        while(true){
            // 最上面一行
            for(int col=left;col<=right;col++){
                list.add(matrix[up][col]);
            }
            // 向下逼近
            up++;
            // 判断是否越界
            if(up > down){
                break;
            }
            // 最右边一行
            for(int row=up;row<=down;row++){
                list.add(matrix[row][right]);
            }
            // 向左逼近
            right--;
            // 判断是否越界
            if(left > right){
                break;
            }
            // 最下面一行
            for(int col=right;col>=left;col--){
                list.add(matrix[down][col]);
            }
            // 向上逼近
            down--;
            // 判断是否越界
            if(up > down){
                break;
            }
            // 最左边一行
            for(int row=down;row>=up;row--){
                list.add(matrix[row][left]);
            }
            // 向右逼近
            left++;
            // 判断是否越界
            if(left > right){
                break;
            }
        }
        return list;
    }
}

T20. 包含 min 函数的栈!

  • 题目描述

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。

  • 解题思路

一个用来存所有的元素“stackTotal”,另一个用来存加入新的元素后当前stackTotal中对应的最小值。
两个栈中的元素数量始终保持一致,当新的元素小于“stackLittle”栈顶元素时,“stackLittle”像栈顶push新来的元素,否则,“stackLittle”向栈顶加入原栈顶元素。
执行“pop”方法时,两个栈同时弹出各自的栈顶元素。

import java.util.Stack;
 
public class Solution {
    Stack<Integer> stackTotal = new Stack<Integer>();
    Stack<Integer> stackLittle = new Stack<Integer>();
 
    public void push(int node) {
        stackTotal.push(node);
        if(stackLittle.empty()){
            stackLittle.push(node);
        }else{
            if(node <= stackLittle.peek()){
                stackLittle.push(node);
            }else{
                stackLittle.push(stackLittle.peek());
            }
        }
    }
 
    public void pop() {
        stackTotal.pop();
        stackLittle.pop();
    }
 
    public int top() {
        return stackTotal.peek();
    }
 
    public int min() {
        return stackLittle.peek();
    }
}

你可能感兴趣的:(算法,java,链表)