3.31周二

今天主要就做了每日一题

效率太低了,一整天感觉就写了个快速排序和堆排序,都是些基础,也摆弄了挺久。这里讲一下力扣的快速排序官方题解的partition函数是有bug的,不过因为他用了随机快排,所以bug比较难触发,这里记录一下[3,1,1,0,3]这个序列就会触发他的partition的bug,所以还是用模板partition比较稳妥(被这个破bug坑了一个上午),这里记录一下我写的solution。

class Solution {
    public int[] sortArray(int[] nums) {
        quickSort(nums,0,nums.length-1);
        return nums;
    }
    public int partition(int[] nums, int l, int r){
        int pivot = nums[l];
        int i=l,j=r;
        while(j>i){
            while(j>i&&nums[j]>pivot)//注意如果pivot选的是最左边的,就需要从最右边开始,反方向类似
                j--;
            nums[i] = nums[j];

            while(j>i&&nums[i]<=pivot){//这里注意需要等于
                i++;
            nums[j] = nums[i];
            }
        }
        nums[i] = pivot;
        return i;
    }
    public void quickSort(int[] nums,int l, int r){
        if(l < r) {//注意这个l<r的条件,不然数组会越界
            int p = partition(nums,l,r);
            quickSort(nums,l,p-1);
            quickSort(nums,p+1,r);
        }   
    }
}

注意以上有注释的几个点,就可以少出点错。
下面讲一下堆排序,之前对堆排序确实了解的也不多,这次好好学习了一下。
堆排序分为两个过程:

  1. 创建小根堆
  2. 不断弹出堆顶元素,进行堆排序
    下面看一下我的solution
class Solution {
    public int[] sortArray(int[] nums) {
        //swap(nums,0,1);
        //heapify(nums,0);
        int length = nums.length;
        heapInit(nums, 0, length);//建立小顶堆
        
        int i=0;
        int[] res = new int[nums.length];
        while(length>0){
            res[i] = pop(nums,length-1);
            length--;
            i++;
        }
        return res;
    }
    //弹出堆顶元素的实现
    public int pop(int[] nums,int last){
        swap(nums,0,last);//首先交换堆顶元素和最后一个元素
        int res = nums[last];//记录堆顶元素
        heapify(nums,0,last);//对堆顶进行一次heapify,因为下面的树都是符合小顶堆的,所以一次heapify就可以了
        return res;
    }
    public void swap(int[] nums, int i, int j){//为了方便实现的swap
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
    public void heapify(int[] nums,int n, int l) {
        if(n>=nums.length) return;
		
		//找到两个孩子节点
        int c1 = n*2 + 1;
        int c2 = n*2 + 2;

		//找到最小的元素并且换到堆顶
        int min = n;
        if((c1 < l) && (nums[c1] < nums[min])) {//注意孩子节点的下标不要越界
            min = c1;
            //System.out.println(nums[0]);
        }
        if((c2 < l) && (nums[c2] < nums[min])) {
            min = c2;
            //System.out.println(nums[0]);
        }
        //换好元素之后,再对被换下来的位置进行heapify,一直递归往下,直到遇到一个符合小顶堆的子树为止
        if(min != n) {
            swap(nums,min,n);
            heapify(nums, min, l);
        }
    }
    
    public void heapInit(int[] nums, int n, int l){//生成小顶堆
        int lastNode = (l - 1) / 2;
        //直接对从最后一个非叶节点开始,按顺序对所有非叶节点进行一次heapify
        for(int i = lastNode;i>=0;i--){
            heapify(nums, i, l);
        }
    }
}

这并不是标准的实现,标准的堆排序应该是用递归实现,因为偷了下懒,而且这样实现也更加直观。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用STM32F103C8T6芯片的定时器3进行倒计时的示例代码,时钟频率为72MHz: 1. 初始化定时器3 ```c void TIM3_Init() { // 使能定时器3时钟 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // 设置预分频器为72-1,即时钟频率为1MHz TIM3->PSC = 71; // 设置自动重载值为999,即定时器3周期为1ms TIM3->ARR = 999; // 使能更新事件 TIM3->CR1 |= TIM_CR1_URS; TIM3->EGR |= TIM_EGR_UG; // 使能定时器3 TIM3->CR1 |= TIM_CR1_CEN; } ``` 2. 设置定时器3的中断 ```c void TIM3_NVIC_Config() { NVIC_InitTypeDef NVIC_InitStructure; // 配置定时器3中断优先级为2,抢占优先级为0,子优先级为2 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 使能定时器3更新中断 TIM3->DIER |= TIM_DIER_UIE; } ``` 3. 定时器3的中断处理函数 ```c void TIM3_IRQHandler() { // 判断是否为定时器3更新中断 if (TIM3->SR & TIM_SR_UIF) { // 更新计数器并判断是否到达0 if (--countdown == 0) { // 关闭定时器3 TIM3->CR1 &= ~TIM_CR1_CEN; // 做其他操作 // 清除计数器 countdown = 0; } // 清除中断标志位 TIM3->SR &= ~TIM_SR_UIF; } } ``` 4. 启动倒计时 ```c void startCountdown(uint16_t time) { // 设置倒计时时间 countdown = time; // 初始化定时器3 TIM3_Init(); // 设置定时器3的中断 TIM3_NVIC_Config(); } ``` 在调用startCountdown函数时,传入需要倒计时的时间(单位为ms),即可启动倒计时。在定时器3的中断处理函数中,每隔1ms更新计数器countdown的值,并判断是否到达0,如果到达0,则关闭定时器3并进行其他操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值