排序和回溯题(2021-7-11)

这篇博客介绍了两种算法的应用。第一部分讲解了使用快速排序算法找到数组中最小的K个数,实现了高效的排序。第二部分则探讨了如何在数据流中实时计算中位数,通过插入排序和二分法保持数据有序,以便快速获取中位数。这些算法在处理大量数据时具有较高的效率。
摘要由CSDN通过智能技术生成

1.最小的K个数

class Solution{
  //快排
     public int[] getLeastNumbers(int[] arr,int k){
        if(k==0||arr.length==0) return new int[0];
         return qsk(arr,0,arr.length-1,k-1);
     }
  private int[] qsk(int[] nums,int l,int r,int k){
         int j=quicksort(nums,l,r);
         //j k对比得到要不要返回前k小的数组
        if(j==k){
          return Arrays.copyOf(nums,j+1);
  }
       //否则要根据j k 大小关系进行调整
      return j>k?qsk(nums,l,j-1,k):qsk(nums,j+1,r,k);
  }
  private int quicksort(int[] nums,int l,int r){
       int v=nums[l];
       int i=l,j=r+1;
       while(true){
       while(++i<=r&&nums[i]<u);
       while(++j>=l&&nums[j]>v);
       if(i>=j) break;
       int temp=nums[i];
       nums[i]=nums[j];
       nums[j]=temp;
  }
      nums[l]=nums[j];
     nums[j]=v;
      return j;//保证nums[j]左边是最小的j个数字
  }
}
思路:快排为最优

2.数据流中的中位数

import java.util.LinkedList;
import java.util.List;
public class Solution{
//插入排序方法,二分法
private List<Integer> list=new LinkedList();
public void Insert(Integer num){
   if(list.size()==0){
       list.add(num);
       return;
   }
   int first=0;//定义起始位置
   int last=list.size()-1;//定义终止位置
   int mid=0;//定义中间数
   while(first<=last){
      mid=(first+last)/2;
      if(list.get(mid)>num)//但集合中间的数>目标值
        last=mid-1;//终止位置为中间位置的数向左移
      else
        first=mid+1;//起始位置从中间位置向右移动
   }
   list.add(first,num);
   return;
}
 public Double GetMedian(){
   int index=list.size();//获取集合的长度
   if(index%2==1){
   return(double)list.get(index/2);
   }
   return ((double)(list.get(index/2-1))+(double)list.get(index/2))/2;
 }
}
思路:1.定义好起始位置,中间位置,截止位置。
2.目标值和中间位置的值比较,如果>中间值,那么起始位置就是中间索引+1
3.如果<中间值,那么终止位置的索引就是中间位置的索引向左-1.
4.集合就为起始位置到目标值。

3.机器人的运动范围

public class Solution{
  public int movingCount(int threshold,int row,int cols){
  //思路分析:利用递归实现,每次只能走上下左右四个点
  //进行判断点的位置是否越界,点数之和是否大于k,是否已经走过
  int flag[][]=new int[rows][cols];
  return helper(0,0,rows,cols,flag,threshold);
  }
  private int helper(int i,int j,int rows,int cols,int[][] flag,int threshold){
  if(i<0||i>=rows||j<0||j>=cols||numSum(i)+numSum(j)>threshold||flag[i][j]==1) return 0;
  flag[i][j]=1;
  //沿着格子按照左右下上的顺序遍历
  return helper(i-1,j,rows,cols,flag,threshold)
  +helper(i+1,j,rows,cols,flag,threshold)
  +helper(i,j-1,rows,cols,flag,threshold)
  +helper(i,j+1,rows,cols,flag,threshold)+1;
  }
  //计算两个坐标数字的和
  private int numSum(int i){
  int sun=0;
  while(i>0){//计算坐标i所有数字的和
    sum+=i%10;
    i=i?10;
  }
  return sum;
  }
}
思路:1.先定义二维数组的横排和竖排。
2.定义一个遍历的方法,遍历的顺序按照左右下上的顺序依次遍历,看哪个方向可以走通。
3.最后计算坐标数字的和。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值