算法数组相关题目(一)

题目0:

给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度0(N),且要求不能用非基于比较的排序。(常考)

思路:借用桶的概念,

第一步,准备桶,如果数组中有n个数,我们就准备N+1个桶,遍历整个数组找到最小值和最大值,如果最小值和最大值相等,说明差值为0,如果不等,最小值放在0号桶,最大值放到N号桶,将最小值到最大值的范围里将桶分为N+1份 ,举例:

数组有9个数,最大值99,最小值0,准备10个桶,所以分为09,1019,…7989,9099这10个范围,中间的数属于哪个范围就放哪个桶

将数都放完后必有一个空桶,并且,在每个桶中,只记录最大值和最小值,还有此桶是否进过数,用Boolean记录,最后计算最大值

代码:

/**
 * @author :LY
 * @date :Created in 2021/3/12 19:46
 * @modified By:
 */
public class 相邻数差值问题 {
    public static int maxGap(int[] nums){
        if (nums == null || nums.length < 2){
            return 0;
        }
        int len = nums.length;
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < len; i++) {
            //获取数组最大值和最小值
            min = Math.min(min,nums[i]);
            max = Math.max(max,nums[i]);
        }
        if (min == max){
            return 0;
        }
        boolean[] hasNum = new boolean[len+1];
        int[] maxs = new int[len + 1];
        int[] mins = new int[len + 1];
        int bid = 0;
        for (int i = 0; i < len; i++) {
            //计算当前数属于几号桶
            bid = bucket(nums[i],len,min,max);
            mins[bid] = hasNum[bid] ? Math.min(mins[bid],nums[i]):nums[i];
            mins[bid] = hasNum[bid] ? Math.max(mins[bid],nums[i]):nums[i];
            hasNum[bid] = true;
        }
        int res = 0;
        int lastMax = maxs[0];
        int i = 1;
        for (; i <= len ; i++) {
            if (hasNum[i]){
                res  = Math.max(res,mins[i] - lastMax);
                lastMax = maxs[i];
            }
        }
        return res;
    }
    public static int bucket(long num,long len,long min,long max){0-99 10
        return (int) ((num-min)*len/(max-min));
    }
}

题目一:

用数组结构实现大小固定的队列和栈

static class ArrayQueue{
        private Integer[] arr;
        private Integer size;
        private Integer start;
        private Integer end;
        public ArrayQueue(int initSize){
            if (initSize < 0){
                throw new IllegalArgumentException("不能为0");
            }
            arr = new Integer[initSize];
            size = 0;
            start = 0;
            end = 0;
        }
        public Integer peek(){
            if (size == 0){
                return null;
            }
            return arr[start];
        }
        public void push(int obj){
            if (size == arr.length){
                throw new ArrayIndexOutOfBoundsException("队列已满");
            }
            size++;
            arr[end] = obj;
            end = end==arr.length -1 ? 0 :end+1;
        }
        public Integer poll(){
            if (size == 0){
                throw new ArrayIndexOutOfBoundsException("队列空");
            }
            size -- ;
            int tmp = start;
            start = start == arr.length -1 ? 0:start +1;
            return arr[tmp];
        }

    }

题目二:

实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。

要求:

1.pop、push、getMin操作时间复杂度都是O(1).

2.设计的栈类型可以使用现成的栈结构

设计思路 准备两个栈 Data栈与min栈

设计思路:data栈压入一个数,min栈同时压入一个数,后续的数依次与min栈栈顶进行比较,压入较小的数,大小相同则再压min栈栈顶,data弹出数min栈也弹出数

题目三:

如何仅用队列结构实现栈结构?

思路:建立两个队列,每次返回一个数就留下最后一个数返回

image.png

public class 队列实现栈 {

    static class TwoQueuesStack{
        private Queue<Integer> queue;
        private Queue<Integer> help;
        public TwoQueuesStack(){
            queue = new LinkedList<>();
            help = new LinkedList<>();
        }
        public void  push(int pushInt){
            queue.add(pushInt);
        }
        public int peek(){
            if (queue.isEmpty()){
                throw new RuntimeException("Stack is empty");
            }
            while (queue.size()!=1){
                help.add(queue.poll());
            }
            int res = queue.poll();
            help.add(res);
            swap();
            return res;
        }
        public int pop(){
            if (queue.isEmpty()){
                throw new RuntimeException("Stack is empty");
            }
            while (queue.size()>1){
                help.add(queue.poll());
            }
            int res = queue.poll();
            swap();
            return res;
        }
        private void swap(){
            Queue<Integer> tmp = help;
            help = queue;
            queue = tmp;
        }
    }
}

如何仅用栈结构实现队列结构?

和上面题目思路相同

需要满足两个行为,一、倒数要倒完 二、被倒的栈不能有数

题目四

image.png

使用两个队列分别存放猫狗,每进来一个就打上时间戳再放入相应的队列中

/**
 * @author :LY
 * @date :Created in 2021/3/14 15:29
 * @modified By:
 */
public class 猫狗队列 {
    public static class Pet{
        private String type;
        public Pet(String type){
            this.type = type;
        }
        public String getPetType(){
            return this.type;
        }
    }
    public static class Dog extends Pet{
        private String type;
        public Dog(String type){
            super("dog");
        }
    }
    public static class Cat extends Pet{
        private String type;
        public Cat(String type){
            super("cat");
        }
    }
    public static class PetEnter{
        private Pet pet;
        private long count;

        public PetEnter(Pet pet,long count){
            this.pet = pet;
            this.count = count;
        }
        public Pet getPet(){
            return this.pet;
        }
        public long getCount(){
            return this.count;
        }
        public String getEnterPetType(){
            return this.pet.getPetType();
        }
    }
    public static class DogCatQueue{
        private Queue<PetEnter> dogQ;
        private Queue<PetEnter> catQ;
        private long count;
        public DogCatQueue(){
            this.dogQ = new LinkedList<>();
            this.catQ = new LinkedList<>();
            this.count = 0;
        }
        public void add(Pet pet){
            if (pet.getPetType().equals("dog")){
                this.dogQ.add(new PetEnter(pet,this.count++));
            }else if (pet.getPetType().equals("cat")){
                this.catQ.add(new PetEnter(pet,this.count++));
            }else {
                throw new RuntimeException("err,not dog or cat");
            }
        }
        public Pet pollAll(){
            if (!this.dogQ.isEmpty() && !this.catQ.isEmpty()){
                if (this.dogQ.peek().getCount() < this.catQ.peek().getCount()){
                    return this.dogQ.poll().getPet();
                }else {
                    return this.catQ.poll().getPet();
                }
            }else if (!this.dogQ.isEmpty()){
                    return  this.dogQ.poll().getPet();
            }else if (!this.catQ.isEmpty()){
                return  this.catQ.poll().getPet();
            }else {
                throw new RuntimeException("err,queue is empty");
            }
        }
        public Dog pollDog(){
            if (!this.dogQ.isEmpty()){
                return (Dog) this.dogQ.poll().getPet();
            }else {
                throw new RuntimeException("err,dogqueue is empty");
            }
        }
        public Cat pollCat(){
            if (!this.catQ.isEmpty()){
                return (Cat) this.catQ.poll().getPet();
            }else {
                throw new RuntimeException("err,catqueue is empty");
            }
        }
        public boolean isEmpty(){
            return this.dogQ.isEmpty()&&this.catQ.isEmpty();
        }
        public boolean isDogEmpty(){
            return this.dogQ.isEmpty();
        }
        public boolean isCatEmpty(){
            return this.catQ.isEmpty();
        }
    }
}

题目五:

转圈打印矩阵

给定一个整型矩阵matrix,请按照转圈方式打印它。例如:

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

打印结果为: 要求额外空间复杂度为O(1)

1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10

image.png

 public static void spiralOrderPrint(int[][] matrix){
      int tR = 0;
      int tC = 0;
      int dR = matrix.length - 1;
      int dC = matrix[0].length - 1 ;
      while (tR <= dR && tC <= dC){
          printEdge(matrix,tR++,tC++,dR--,dC--);
      }
  }

    /**
     *
     * @param m
     * @param tR 左上角的行
     * @param tC 左上角的列
     * @param dR 右下角的行
     * @param dC 右下角的列
     */
  public static void printEdge(int[][] m,int tR,int tC,int dR,int dC){
      if (tR == dR){
          for (int i = tC; i <= dC ; i++) {
              System.out.println(m[tR][i] + " ");
          }
      }else if (tC == dC){
          for (int i = tR; i <= dR ; i++) {
              System.out.println(m[i][tC] + " ");
          }
      }else {
          int curC = tC;
          int curR = tR;
          while (curC != dC){
              System.out.println(m[tR][curC] + " ");
              curC++;
          }
          while (curR != dR){
              System.out.println(m[curR][dC] + " ");
              curR++;
              while (curC != tC){
                  System.out.println(m[dR][curC] + " ");
                  curC--;
              }
              while (curR != tR){
                  System.out.println(m[curR][tC] + " ");
                  curR--;
              }
          }
      }
  }

题目六

"之"字形打印矩阵

给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如:

1 2 3 4

5 6 7 8

9 10 11 12

image.png

核心是写一个打对角线的函数

/**
 * 打印之字形数组
 * @author :LY
 * @date :Created in 2021/3/16 10:43
 * @modified By:
 */
public class 之字形打印数组 {

    public static void main(String[] args) {
        int[][] arr = new int[3][3];
        arr[0][0]=1;
        arr[0][1]=2;
        arr[0][2]=3;
        arr[1][0]=5;
        arr[1][1]=6;
        arr[1][2]=7;
        arr[2][0]=9;
        arr[2][1]=10;
        arr[2][2]=11;
        printMatrixZigZag(arr);
    }

    public static void printMatrixZigZag(int[][] matrix){
        int tR = 0;//左上角的行
        int tC = 0;//左上角的列
        int dR = 0;//右下角的行
        int dC = 0;//右下角的列
        int endR = matrix.length -1;
        int endC = matrix[0].length - 1;
        boolean fromUp = false;
        while(tR != endR + 1){
            printLevel(matrix,tR,tC,dR,dC,fromUp);
            tR = tC == endC ? tR + 1: tR;
            tC = tC == endC ? tC : tC + 1;
            dC = dR == endR ? dC + 1 : dC;
            dR = dR == endR ? dR : dR + 1;
            fromUp = !fromUp;
        }
    }
    public static void printLevel(int[][] m,int tR,int tC,int dR,int dC,boolean f){
        if (f){
            while (tR != dR+1){
                System.out.println(m[tR++][tC--] + " ");
            }
        }else {
            while (dR != tR - 1){
                System.out.println(m[dR--][dC++] + " ");
            }
        }
    }
}

题目7

在行列都排好序的矩阵中找数

给定一个有N*M的整型矩阵matrix和一个整数K,matrix的每一行和每一列都是排好序的。实现一个函数,判断K是否在matrix中。例如:

0 1 2

1 2 3

6 7 8

如果k为7,返回true,如果k为6,返回false。 要求时间复杂度为0(N+M),额外空间复杂度为O(1)。

思路分析:假设需要找4,从右上角开始找,如果比4大,直接将当前整列排除(因为是排好序的),往左移,继续刚才的操作

image.png

public class 矩阵找数 {
    public static void main(String[] args) {
        int[][] arr = new int[3][4];
        arr[0][0]=1;
        arr[0][1]=3;
        arr[0][2]=5;
        arr[0][3]=6;
        arr[1][0]=2;
        arr[1][1]=5;
        arr[1][2]=7;
        arr[1][3]=9;
        arr[2][0]=4;
        arr[2][1]=6;
        arr[2][2]=8;
        arr[2][3]=10;
        printHit(arr,8);
    }

    public static void printHit(int[][] arr,int num){
        //拿到右上角的坐标
        int tR = 0;
        int tC = arr[0].length-1;
        int dR = arr.length-1;
        int dC = -1;
        while (tR != dR || tC != dC){
            if (arr[tR][tC] == num){
                System.out.println("已找到");
                break;
            }
//            if (arr[tR][tC] > num){
//                tC--;
//
//            }else {
//                tR ++;
//
//            }
            tC = arr[tR][tC] > num?tC-1:tC;
            tR = arr[tR][tC] < num?tR+1:tR;
        }
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值