zoukankan      html  css  js  c++  java
  • leetcode数组题

    数组算法

    完美洗牌算法

    c语言随机数如何产生:

    利用srand((unsigned int)(time(NULL))是一种方法,因为每一次运行程序的时间是不同的。

    在C语言里所提供的随机数发生器的用法:现在的C编译器都提供了一个基于ANSI标准的伪随机数发生器函数,用来生成随机数。它们就是rand()和srand()函数。这两个函数的工作过程如下:

    1) 首先给srand()提供一个种子,它是一个unsigned int类型,其取值范围从0~65535;

    2) 然后调用rand(),它会根据提供给srand()的种子值返回一个随机数(在0到32767之间)

    3) 根据需要多次调用rand(),从而不间断地得到新的随机数;

    4) 无论什么时候,都可以给srand()提供一个新的种子,从而进一步“随机化”rand()的输出结果。

    下面是0~32767之间的随机数程序:

    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>//使用当前时钟做种子
    
    void main( void )
    {
    
      int i;
      srand( (unsigned)time( NULL ) ); //初始化随机数
      for( i = 0; i < 10;i++ ) //打印出10个随机数
        printf( " %d
    ", rand() );
    }

    完美洗牌算法:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>//使用当前时钟做种子
        
    int main () {
        int arr[10] ={2,5,3,23,5,4,22,44,776,45};
        int temp;
        int index;
            int i;
        srand((unsigned)time(NULL));//初始化随机数
        for(i=10-1;i>=0;i--)
        {    
            temp = arr[i];
            index = rand() %(i + 1);//生成0-i的随机数
            //rand() % 10:生成[0,9]的整数随机数
            //rand() % 10+5:生成[5,14]的整数随机数
            arr[i] = arr[index];
            arr[index] = temp;
        }
        for(i=0;i<10;i++)
        {    
            printf("%d
    ",arr[i]);
        }
        return 0;
    }

    窗口大小为K的最大子数组和:利用滑动窗口

    #include <stdio.h>
    
    #define k 3 //定义滑动窗口的大小
        
    int main () {
        int list[15] = {5,23,86,21,43,67,45,34,58,23,102,123,11,22,1};
        int i = 0;//数组下标
        int j; //滑动窗口的起始头
        int sum = 0;  //临时结果
        int maxsum = sum; //最后的结果
        while(i+k-1<15){for(j = i;j<i+k;j++)
            {
                sum = sum +list[j];
            }
            if(sum>maxsum) maxsum = sum;
            sum = 0;
            i++;
        }
        printf("%d
    ",maxsum);
    }

    寻找最小的k个数

    假定最小的k个数,遍历数组以后的n-k个数,依次替换掉这k个数里的最大值。

    #include <stdio.h>
        
    #define size 2 //k个数
    int arr[10] ={2,5,3,23,5,4,22,44,776,45};    
    int minarr[size] = {2,5};
    
    int Getmaxindex(){
        int min = minarr[0];
        int i =1;
        int index = 0;
        for(;i<size;i++)
        {   //找到最大值
            if(minarr[i]>min){
                min = minarr[i];
                index = i;
            } 
        }
        return index;
    }    
        
    int main () {
        int maxnumindex; //定义每次从minarr返回最大值的下标
        int maxnum; //定义minarr中的最大值
        int i = size -1; //继续从size-1的位置开始遍历往后的元素
        while(i<10){
            //得到最大值下标
            maxnumindex = Getmaxindex(minarr);
            //得到最大值
            maxnum = minarr[maxnumindex];
            //继续遍历
            //如果继续遍历得到的值比minarr数组中最大的值大,将这个最大值替换成这个值
            if(arr[i]<maxnum){
                minarr[maxnumindex] = arr[i];
            }
            i++;
        }
        for(i = 0; i<size;i++){
            printf("%d
    ",minarr[i]);
        }
        return 0;
    }

    寻找和为定值的两个数:有序数组与双向滑动指针

    #include <stdio.h>
    int main () {
        int sum = 124;
        int list[15] = {5,23,86,21,43,67,45,34,58,23,102,123,11,22,1};
        
        //对数组进行选择排序:从小到大////////
        int i, j, temp,min;
        for(i = 0; i< 15;i++)
        {
    //令最小值等于无序区的第一个值
            min = list[i];
    //找到无序区的最小值
            for(j = i; j<15;j++)
            {
                if(min>list[j])
                {
                    temp = min;
                    min = list[j];
                    list[j] = temp;
                }
            }
            list[i] = min;
        }
        //for (i = 0;i < 15; i++)
           // printf("%d
    ",list[i]);
        /////////////////////
        
        ///有序:从小到大的序列中找到满足x+y =sum的x与y元素//
        int start = 0;
        int end = 14;
        int currsum = 0;
        while(start<end){
            currsum = list[start] +list[end];
            if(currsum == sum)
            {
              printf("currsum == sum:%d+%d=%d
    ",list[start],list[end],currsum);
              //i++;
              //j--; //寻找其它x与y可以去掉这两行注释
              break;
            }else{
                //如果currsum比sum小,只需要移动start指针
                if(currsum < sum){start++;} 
                //如果currsum比sum大,只需要移动end指针
                else{end--;}     
            }
        }
    }

    数组中出现次数超过一半的数字

    如果一个数出现的次数超过数组一半的长度,那么就是说出现的次数比其他所有数字出现的次数还要多。因此我们可以考虑保存2个值,一个是数组中的一个数,一个是数的次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加1,如果不同则次数减1。如果次数为0了这保存当前遍历到的数,并把次数设为1。遍历完整个数组之后,返回当前保存的数字,即是我们要找的数字。

    #include <stdio.h>
    
    int numbers[] = {3,3,2};
    int result = 3;    
    
    int MoreThanHalfNum(int length)
    {    
        
        int count = 1 ;
        int i;
        //从下标为1开始遍历
        for (i = 1 ;i < length ; i++)
        {
           
            if (numbers[i] == result)
            {
                count++;
            }
            else 
            {
                count-- ;
            }
             if (count == 0)
            {
                result = numbers[i] ;
                count++ ;
            }
            
        }
        return count;
    }
    int main()
    {
        int count = MoreThanHalfNum(3);
        if(count>0){
            printf("出现次数超过一半:%d",result);
        }else if(count==0){
            printf("出现次数与其它所有数相等:%d
    ",result);
        }else{
            printf("没有");
        }
        return 0;
    }

    寻找二维数组递增数组的一个数

    在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

    #include <stdio.h>
        
    int matrix[5][5] = {
                    {1,4,7,11,15},
                    {2,5,8,12,19},
                    {3,6,9,16,22},
                    {10,13,14,17,24},
                    {18,21,2326,30},
            };
    int find(int num){
            int r = 0,c = 5 - 1;//从右上角开始
            while (r <= 5 - 1 && c >= 0) {
                if (num == matrix[r][c]) {
                    return 1;
                } else if (num > matrix[r][c]) {
                    r++;
                } else {
                    c--;
                }
            }
            return 0;
    }    
        
        
        
    int main () {
        int flag = find(17);
        printf("%d
    ",flag);
        return 0;
    }

    奇偶数排序

      给定一个整数数组,请调整数组中数的顺序,使得所有奇数位于数组的前半部分,偶数位于后半部分。

    使用两个指针,一个指向头,一个指向尾,两个指针从数组头部和尾部向数组中间一段,如果头指针指向的是偶数,尾指针指向的是奇数,就交换两个数。

    #include <stdio.h>
    
    
    //判断奇偶数
    int isoaddnumber(int num){
        return num&1;
    }
    
    //
    void OddEvenSort(int *pData,int length){
        //头指针
        int *pstart = pData;
        //尾指针
        int *pend = pData + length - 1;
        int temp;
        while(pstart < pend){
            //如果pstart指针指向的时奇数,正常,向右移
            if(isoaddnumber(*pstart)){
                pstart ++;
            }
            //如果pend指针指向的时偶数,正常,向左移
            else if(isoaddnumber(*pend)==0){
                pend --;
            }
         //都不正常则交换两个数
    else{ temp = *pstart; *pstart = *pend; *pend = temp; } } } int main() { int numbers[] = {3,2,8,56,34,5,9,32,23}; int i =0; OddEvenSort(numbers,9); for(;i<9;i++) printf("%d ",numbers[i]); return 0; }

     

    荷兰国旗

    将n个红白蓝标题颜色的小球排序为,红、白、蓝,假设红为0,白为1,蓝为2

    输入一组{0,1,2,1,2,0,2,0,1,2,0,1,1},返回{0,0,0,0,1,1,1,1,2,2,2,2}

    #include <stdio.h>
    
    
    void Sort(int *pData,int length){
        //头指针
        int *pstart = pData;
        //尾指针
        int *pend = pData + length - 1;
        //中指针
        int *pcurrent = pData;
        //临时变量
        int temp;
        
        while(pcurrent <= pend){
            //current指针指向元素为0
            //与start指针所指元素交换,current++,start++
            if(*pcurrent ==0){
                temp = *pstart;
                *pstart = *pcurrent;
                *pcurrent = temp;
                
                pstart ++;
                pcurrent++;
            }
            //current指针指向元素为1,不做任何交换,current++
            else if(*pcurrent ==1){
                pcurrent ++;
            }
            else{//current指针指向元素为2,与end指针所指元素交换,current不动,end--
                temp = *pcurrent;
                *pcurrent = *pend;
                *pend = temp;
                pend--;
            }
        }
    }
    int main() { int numbers[] = {0,1,2,1,2,0,2,0,1,2,0,1,1}; int i =0; Sort(numbers,12); for(;i<12;i++) printf("%d ",numbers[i]); return 0; }

    删除有序数组中的重复值

    原文链接

    如何去除有序数组的重复元素

    我们知道对于数组来说,在尾部插入、删除元素是比较高效的,时间复杂度是 O(1),但是如果在中间或者开头插入、删除元素,就会涉及数据的搬移,时间复杂度为 O(N),效率较低。

    所以对于一般处理数组的算法问题,我们要尽可能只对数组尾部的元素进行操作,以避免额外的时间复杂度。

    这篇文章讲讲如何对一个有序数组去重,先看下题目:

    显然,由于数组已经排序,所以重复的元素一定连在一起,找出它们并不难,但如果毎找到一个重复元素就立即删除它,就是在数组中间进行删除操作,整个时间复杂度是会达到 O(N^2)。而且题目要求我们原地修改,也就是说不能用辅助数组,空间复杂度得是 O(1)。

    其实,对于数组相关的算法问题,有一个通用的技巧:要尽量避免在中间删除元素,那我就想先办法把这个元素换到最后去。这样的话,最终待删除的元素都拖在数组尾部,一个一个 pop 掉就行了,每次操作的时间复杂度也就降低到 O(1) 了。

    按照这个思路呢,又可以衍生出解决类似需求的通用方式:双指针技巧。具体一点说,应该是快慢指针。

    我们让慢指针 slow 走左后面,快指针 fast 走在前面探路,找到一个不重复的元素就告诉 slow 并让 slow 前进一步。这样当 fast 指针遍历完整个数组 nums 后,nums[0..slow] 就是不重复元素,之后的所有元素都是重复元素。

    int removeDuplicates(int[] nums) {
        int n = nums.length;
        if (n == 0) return 0;
        int slow = 0, fast = 1;
        while (fast < n) {
            if (nums[fast] != nums[slow]) {
                slow++;
                // 维护 nums[0..slow] 无重复
                nums[slow] = nums[fast];
            }
            fast++;
        }
        // 长度为索引 + 1
        return slow + 1;
    }

    看下算法执行的过程:

    再简单扩展一下,如果给你一个有序链表,如何去重呢?其实和数组是一模一样的,唯一的区别是把数组赋值操作变成操作指针而已:

    ListNode deleteDuplicates(ListNode head) {
        if (head == null) return null;
        ListNode slow = head, fast = head.next;
        while (fast != null) {
            if (fast.val != slow.val) {
                // nums[slow] = nums[fast];
                slow.next = fast;
                // slow++;
                slow = slow.next;
            }
            // fast++
            fast = fast.next;
        }
        // 断开与后面重复元素的连接
        slow.next = null;
        return head;
    }
  • 相关阅读:
    Oracle中的substr()函数和INSTR()函数和mysql中substring_index函数字符截取函数用法:计算BOM系数用量拼接字符串*计算值方法
    (转载)SDRAM驱动笔记
    【转】Verilog阻塞与非阻塞赋值使用要点
    【转转】(筆記) always block內省略else所代表的電路 (SOC) (Verilog)
    (原創) 如何處理signed integer的加法運算與overflow? (SOC) (Verilog)
    [转载]亚稳态
    Dev Exprss 发布部署
    Dev splliter 去除中间的分割显示
    DevTreeList中的新增、修改的设计
    Oracle 常用网址
  • 原文地址:https://www.cnblogs.com/-wenli/p/12456991.html
Copyright © 2011-2022 走看看