求职系列笔记(1)---数据结构和算法

数组涉及到的算法相当多,主要分为:排序算法、查找算法等。
(a)二分查找主要有两种,一种是基于除法的,一种基于加减的(也叫:斐波那契查找法、黄金查找法)

/*二分查找的算法如下(1):*/
    int binarySearch(int arr[],int n,int value)//查找区间为[0,n-1]
    {
        int low=0;
        int high=n-1;
        while(low<=high)//这个条件很讲究
        {
            int mid=low+(high-low)>>1;
            if(arr[mid]<value) low=mid+1;
            else if(arr[mid]>value) high=mid-1;
            else return mid;//这个很有讲究,如果放到最后,可以节省很多时间;
        }
        return -1;//说明没有查找到
    }
    /*二分查找的算法如下(2):*/
    int binarySearch(int arr[],int n,int value)//查找区间为[0,n-1]
    {
        int low=0;
        int high=n-1;
        while(low<high)//这个条件很讲究
        {
            int mid=low+(high-low)>>1;
            if(arr[mid]<value) low=mid;
            else if(arr[mid]>value) high=mid;
            else return mid;//这个很有讲究,如果放到最后,可以节省很多时间;
        }
        return -1;//说明没有查找到
    }

/排序算法,主要掌握快排、归并排序、堆排序; 至于其他的冒泡、选择、插入、桶排序等很容易掌握;/

/*快排算法,主要基于递归和快速划分函数partition*/
    int partition(int arr[],int low,int high)//划分区间为[low,high]
    {
        int temp=arr[low];//找到一个基准点
        while(low<high)
        {
            while((low<high)&&(arr[high]>temp)) high--;
            swap(arr[low],arr[high]);
            while((low<high)&&(arr[low]<=temp)) low++;          
            swap(arr[low],arr[high]); 
        }
        return low;
    }
    void quicksort(int arr[],int low,int high)//n为数组长度
    {
        if(low>=high) return;//条件改为if(low>=high)也可以,因为指向同一个元素,可以不划分;
        int provit=partition(arr,low,high);
        quicksort(arr,low,provit-1);
        quicksort(arr,provit+1,high);
    }
//思考,快排时间复杂度为o(n*logn),最差情况下为:o(N^2)

本文继续探讨partition函数的其他应用,这是一种思想,特别重要;
基于快速排序partition思想的算法拓展
(1)输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,
所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
(2)荷兰国旗问题:这个问题类似快排中partition过程,
只是需要用到三个指针:一个前指针begin,一个中指针current,一个后指针end,
current指针遍历整个数组序列,当
(a)current指针所指元素为0时,与begin指针所指的元素交换,而后current++,begin++;
(b)current指针所指元素为1时,不做任何交换(即球不动),而后current++;
(c)current指针所指元素为2时,与end指针所指的元素交换,而后,current指针不动,end–;

参考代码如下:
while( current<=end )        
{             
  if( array[current] ==0 )             
   {                 
      swap(array[current],array[begin]);                  
      current++;                  
      begin++;            
   }             
   else if( array[current] == 1 )            
   {                 
      current++;            
   }   
   else //When array[current] =2   
   {               
      swap(array[current],array[end]);                
      end--;            
   }      
}  

关于这部分,可以参考如下:
(1)奇偶调序 http://taop.marchtea.com/02.06.html
(2)荷兰国旗 http://taop.marchtea.com/02.07.html

继续学习其他排序算法,归并排序

/*二路归并排序,这个算法应用很广泛,也是稳定算法*/ 
    void mergearray(int a[],int temp[],int first,int mid,int last)//将有二个有序数列a[first...mid]和a[mid...last]合并。  
    {  
        int i=first, j=mid + 1;  
        int m=mid,n=last;  
        int k=0;  
        while(i<= m && j<= n)  
        {  
            if(a[i]<=a[j]) temp[k++]=a[i++];  
            else temp[k++]=a[j++];  
        }    
        while(i<=m) temp[k++]=a[i++];   
        while(j<=n) temp[k++]=a[j++];  
        for(i=0;i<k;i++)  
            a[first+i]=temp[i];  
    }  
    void Merge(int arr[],int copy[],int low,int high)//处理主体函数,递归实现划分、合并
    {
        if(low<high)  
        {  
            int mid=(low+high)>>1;  
            mergesort(arr,copy, low, mid);    //左边有序  
            mergesort(arr, copy,mid + 1,high); //右边有序  
            mergearray(arr,copy,low,mid,high); //再将二个有序数列合并  
        }  
    }
    void Mergesort(int arr[],,int low,int high)//调用接口函数;
    {
        int* copy=new int[];
        Merge(arr,copy,low,high);
    }

/*
思考,归并排序时间复杂度o(n*logn),稳定排序,消耗o(n)空间复杂度;
参考《剑指offer》中数组中的逆序对,也是采用归并排序的方法。
参考代码如下:

 class Solution {
public:
    int InversePairs(vector<int> data) {
        if(data.size()<=1) return 0;
        int* copy=new int[data.size()];
        //初始化数组
        for(unsigned int i=0;i<data.size();i++)
            copy[i]=0;
        int count=InversePairCore(data,copy,0,data.size()-1);
        delete[] copy;
        return count;
    }
    int InversePairCore(vector<int>& data,int*& copy,int start,int end)
    {
        if(start==end)
        {
            copy[start]=data[start];
            return 0;
        }
        //将数组拆分成两部分
        int length=(end-start)/2;
        //分别计算左边部分和右边部分
        int left=InversePairCore(data,copy,start,start+length);
        int right=InversePairCore(data,copy,start+length+1,end);
        //进行逆序计算
        int i=start+length;
        int j=end;
        int index=end;
        int count=0;
        while(i>=start && j>=start+length+1)
        {
            if(data[i]>data[j])
            {
                copy[index--]=data[i--];
                //统计长度
                count+=j-start-length;
            }
            else
            {
                copy[index--]=data[j--];
            }
        }
        for(;i>=start;--i)
        {
            copy[index--]=data[i];
        }
        for(;j>=start+length+1;--j)
        {
            copy[index--]=data[j];
        }
        //排序
        for(int i=start; i<=end; i++) {
            data[i] = copy[i];
        }
        //返回最终的结果
        return (count+left+right);
    }
};

*/
数组在其他的应用,如用一个数组实现三个栈;
参考代码如下:

class stack3{
public:
    stack3(int size = 300){
        buf = new int[size*3];
        ptop[0]=ptop[1]=ptop[2]=-1;//三个栈底分别指向-1
        this->size = size;
    }
    ~stack3(){
        delete[] buf;
    }
    void push(int stackNum, int val)//stackNum为0,1,2分别代表栈
    {
        int idx = stackNum*size + ptop[stackNum] + 1;//求出栈的
        buf[idx] = val;
        ++ptop[stackNum];
    }
    void pop(int stackNum)//弹栈
    {
        --ptop[stackNum];
    }
    int top(int stackNum)//栈顶元素
    {
        int idx = stackNum*size + ptop[stackNum];
        return buf[idx];
    }
    bool empty(int stackNum)//判断栈空
    {
        return ptop[stackNum]==-1;
    }
private:
    int *buf;
    int ptop[3];
    int size;
};

数组的排序算法中,主要讲了快排、归并排序,这两个排序的思想应用广泛。至于其他排序,可以自行学习。
总结,数组是一种最常用的数据结构,在动态规划中、在回溯法中进行修枝中也起到很大重要。详见下一期内容;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值