算法初级_2 :数组和指针

数组指针基础

  • 数组和指针
#include<iostream>
using namespace std;

int main(int args,char *argv[])
{
   int a[3];
   int* p=a;
   p[0]=1949;
   p[1]=1978;
   p[2]=2015;
   cout<<a[0]<<'\t'<<a[1]<<'\t'<<a[2]<<endl;

   return 0;
}
  • 指针数组:数组的每个元素都是指针
#include<iostream>
using namespace std;

int main(int args,char *argv[])
{
  int a,b,c;
  int *p[3];
  p[0]=&a;
  p[1]=&b;
  p[2]=&c;
  *p[0]=3;
  *p[1]=6;
  *p[2]=9;
  cout<<a<<'\t'<<b<<'\t'<<c<<endl;

  return0;
}
  • 数组指针:很少用
int *q=a; //指向a[]首地址的指针
int (*p)[3]=&a; //指向数组的指针
  • 二维数组
int main(int args,char *argv[])
{
    int a[2][3];
    int *p=a[0];
    int *q=a[1];

    p[0]=1;p[1]=2;p[2]=3;
    q[0]=4;q[1]=5;q[2]=6;

    cout<<a[0][0]<<'\t'<<a[0][1]<<'\t'<<a[0][2]<<'\n';
    cout<<a[1][0]<<'\t'<<a[1][1]<<'\t'<<a[1][2]<<'\n';
}

//传递参数

void  f(int a[2][3])
{...}
void f2(int a[][3])
{...}

int main()
{
     int a[2][3];
     f(a);
     f2(a);
     ...
}

vector

  • 用例
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main(int argc,char* argv[])
{
    vector<int> a;
    a.push_back(1);
    a.push_back(2);
    a.push_back(3);
    a.push_back(4);

    for(int i=0;i<(int)a.size();i++)
        cout<<a[i]<<'\t';

    cout<<endl;
    return 0;
}
  • a.capacity:vector的容量
  • 重新分配,元素移动,释放原空间
//理论是2倍
//实际vs下是1.5倍

hash

c语言版本

  • 散列技术:记录存储位置和关键字之间的确定关系
    存储位置=f(关键字)
  • 散列函数构造方法

    1. 计算简单;2. 散列地址分布均匀
  • 直接定址法:取关键字的某个线性函数值为散列地址
    f(key)=a*key+b (a、b是常数)

折半查找

#include <iostream>
using namespace std;

int Find(const int* array,int size, int a) //size=数组大小,a=指定元素
{
    int nFrom=0;
    int nTo=size-1;
    int nIndex;
    bool bFind=false;
    while(nFrom <= nTo)
    {
        nIndex=nTo+(nFrom-nTo)/2;
        if(array[nIndex==a])
        {
            bFind=true;
            break;
        }
        if(array[nIndex]>a)
            nTo=nIndex-1;
        else
            nFrom=nIndex+1
    }

    if(bFind)
        return nIndex;

    return -1;
}

字符循环左移

  • 给定字符S[0, …, n-1];把S的前K个字符移动到S的尾部
    例如:
    ‘abcdef’—>’cdefab’, k=2

  • 复杂度:O(n), 空间复杂度=O(1)

*算法比较:
1. 暴力:循环左移1位,调用K次;时间复杂度:O(KN),空间:O(1)
2. 三次拷贝:S[0,…,K]->T[0…N-k-1];S[k+1,…N-1]->S[0,…,N-K-1];T[0…k]->S[N-K…N-1]
时间:O(N),空间O(K)
3. (X’Y’)’=YX
X=ab;X’=ba
Y=cdef;Y’=fedc
(X’Y’)’=(bafedc)’=cdefab
时间:O(N);空间:O(1)

void ReverseString(char *s,int from,int to)
{
    while(from<to)
    {
        char t=s[from];
        s[from++]=s[to];
        s[to--]=t;
    }
}

void LeftRotateString(char *s,int n,int m)
{
    m%=n;
    ReverseString(s,0,m-1);
    ReverseString(s,m,n-1);
    ReverseString(s,0,n-1);
}

twosum

  • 给定数组A[0…N-1]和一个数组sum, 在数组中查找数 Ai,Aj 使得 Ai+Aj=sum
  • 暴力:
    时间: O(N2) ; 空间 O(1)
  • 双指针
    1. 先排序: O(NlgN)
    2. 双指针查找:O(N)
      双指针:i=0;j=n-1;
      a[i]+a[j]>sum; i不变,j–;
      a[i]+a[j]
#include <stdio.h> 
#include <string.h> 
#include <queue> 
using namespace std;  

class Solution {
    public:
        vector<int> twoSum(vector<int> &numbers, int target) {
            int sz = numbers.size();
            int left = 0, right = sz - 1, sum = 0;

            vector<int> sorted (numbers);
            std::sort(sorted.begin(), sorted.end());

            vector<int> index;
            while (left < right) {
                sum = sorted[left] + sorted[right];
                if (sum == target) {
                    // find the answer
                    for (int i = 0; i < sz; i++) {
                        if (numbers[i] == sorted[left])
                            index.push_back(i + 1);
                        else if (numbers[i] == sorted[right])
                            index.push_back(i + 1);
                        if (index.size() == 2)
                            return index;
                    }
                } else if (sum > target) {
                    right--;
                } else {
                    left++;
                }
            }
         }
};

int main ()
{
    Solution s1;
    int num[] ={0, 2, 4, 0};
    vector<int> numbers (num,num+4);
    int target = 0;
    vector<int> result = s1.twoSum(numbers, target);
    for(int i = 0 ;i < result.size(); i++)
    {
        cout<< result[i]<<endl;
    }
    return 0;
}

http://doc.okbase.net/waycaiqi/archive/149187.html

hash算法

//hashset
public class Solution {
    public int[] twoSum(int[] nums, int target) {
        int index1,index2;
        int[] index=new int[]{0,1};
        Set nset = new HashSet();

        for(int i = 0; i< nums.length; i++)
        {
           if(nset.add(target-nums[i])) //检查是否有nums[i]配对的元素存在,无则添加成功 
           {
               nset.remove(target-nums[i]); //添加该元素只是为了判断是否存在,本来不应该添加的这里又删掉
               nset.add(nums[i]);
           }else
           {
               index[1] = i+1;
               for(int j = 0; j< i; j++)
               {
                   if(target==(nums[i]+nums[j]))
                   {
                       index[0] = j+1;
                       return index;
                   }
               }
               return index;
           }

        }
        return index;
    }

}
 //hashmap
 public class Solution {  
    public int[] twoSum(int[] nums, int target) {  
        int[] index=new int[]{0,1};
        HashMap<Integer,Integer> hm = new HashMap<Integer,Integer>();

        for(int i = 0; i<nums.length; i++)
        {
            if(hm.containsKey(target - nums[i]))
            {
                index[1] = i+1;
                index[0] = hm.get(target-nums[i])+1;   
                return index;   
            }else
            {
                 hm.put(nums[i],i);
            }
        }
        return index;  
    }

}  

荷兰国旗

  • 红白蓝三种颜色小球,乱序的排列在一起,重新排列,使得红白蓝三色,同色的在一起。

算法:
* 生成:00…0011…1122…22 的形式

//定义三个指针:begin=0,current=0,end=N-1;
1. A[cur]==2, 则A[cur]和A[end]交换,end–,cur不变
2. A[cur]==1, 则cur++,begin不变和end不变
3. A[cur]==0 ,则
3.1………. 若begin==cur,则begin++,cur++
3.2………. 若begin不等于cur,则A[cur]和A[begin]交换,begin++,cur不变

void Holland(int* a,int length){
    int begin=0;
    int current=0;
    int end=length-1;
    while(current<=end){
       if (a[current]==2){
           swap(a[end],a[current]);
           end--;
       }
       else if(a[current]==1){
           current++;
       } 
       else if(a[current]==0){
           if(begin==current){
               begin++;
               current++;
           }
           else {
               swap (a[current],a[end]);
               begin++;
           }
       }

    }
}
  • 优化版本
  • current扫描的位置[begin, current) 中一定没有2
  • A[cur]==0,且 begin不等于cur时, 因为A[begin]==1,交换后,A[cur]==1
    此时,cur++;
void Holland(int* a,int length){
    int begin=0;
    int current=0;
    int end=length-1;
    while(current<=end){
       if (a[current]==2){
           swap(a[end],a[current]);
           end--;
       }
       else if(a[current]==1){
           current++;
       } 
       else if(a[current]==0){
           if(begin==current){
               begin++;
               current++;
           }
           else {
               swap (a[current],a[end]);
               begin++;
              current++;  //添加的代码
           }
       }       
    }
}
//代码重构
void Holland(int* a,int length){
    int begin=0;
    int current=0;
    int end=length-1;
    while(current<=end){
       if (a[current]==2){
           swap(a[end],a[current]);
           end--;
       }
       else if(a[current]==1){
           current++;
       } 
       else {
           if(current!=begin)
              swap(a[current],a[begin]);
            begin++;
            current++;
       }
    }
}

你可能感兴趣的:(算法初级_2 :数组和指针)