LeetCode第 20 場雙週賽

1.根據數字二進制下 1 的數目排序

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
 int cal(int num){
     int sum=0;
     while(num){
         sum+=num%2;
         num/=2;
     }
     return sum;
 }
int* sortByBits(int* arr, int arrSize, int* returnSize){
    int  i,tmp,j;
    int *onenum=(int*)malloc(sizeof(int)*(arrSize+1));
    for(i=0;i<arrSize;i++){
        onenum[i]=cal(arr[i]);
    }
   for(i=0;i<arrSize-1;i++){
       for(j=i+1;j<arrSize;j++){
           if(onenum[i]>onenum[j]||(onenum[i]==onenum[j]&&arr[i]>arr[j])){
               tmp=onenum[i];
               onenum[i]=onenum[j];
               onenum[j]=tmp;
               tmp=arr[i];
               arr[i]=arr[j];
               arr[j]=tmp;
           }
       }
   }
   *returnSize=arrSize;
    return arr;
}

2.每隔 n 個顧客打折

typedef struct {
    int n;
    int now;
    int discount;
    int* products;
    int productsSize;
    int* prices;
    int pricesSize;
} Cashier;

Cashier* cashierCreate(int n, int discount, int* products, int productsSize, int* prices, int pricesSize) {
    Cashier* t=(Cashier*)malloc(sizeof(Cashier));
    t->n=n;t->now=0;
    t->discount=discount;
    t->products=products;
    t->productsSize=productsSize;
    t->prices=prices;
    t->pricesSize=pricesSize;
    return t;
}

double cashierGetBill(Cashier* obj, int* product, int productSize, int* amount, int amountSize) {
    obj->now++;
    double sum=0;
    for(int i=0;i<productSize;i++){
        for(int j=0;j<obj->productsSize;j++){
            if(obj->products[j]==product[i]){
                sum=sum+obj->prices[j]*amount[i];break;
            }
        }
    }
    if(obj->now==obj->n){
        sum=sum-(obj->discount*sum)/100;
        obj->now=0;
    }
    return sum;
}

void cashierFree(Cashier* obj) {
free(obj);
}

/**
 * Your Cashier struct will be instantiated and called as such:
 * Cashier* obj = cashierCreate(n, discount, products, productsSize, prices, pricesSize);
 * double param_1 = cashierGetBill(obj, product, productSize, amount, amountSize);
 
 * cashierFree(obj);
*/

3.包含所有三種字符的子字符串數目

【思路】考慮子串是否包含abc,且重複的子串也算。我們每次從i開始遍歷,計算i開始的字符串中有多少個符合要求的子串。如果採用雙循環,會超時。在這裏需要優化一下,其實遍歷i開始的字符串我們只需要保存上一次遍歷的末尾 j,而j前面遍歷的結果已經存在數組d中。

我們用一個數組d[3]來存放出現的abc的次數。如果d[0],d[1],d[2]都不爲0,表示當前子串已經出現了abc字母,那麼接下來j後面的字符無需遍歷,因爲再加入任何一個字符,都可以組成符合要求的字符串。

int numberOfSubstrings(char * s){
    int i,j=0,len,sum=0,tmp;
    int d[3]={0};
    len=strlen(s);
    if(len<3)return 0;
    for(i=0;i<len;i++){
        while(j<len&&(d[0]==0||d[1]==0||d[2]==0)){
            d[s[j]-'a']++;
            j++;
        }
        if(!(d[0]==0||d[1]==0||d[2]==0)){
            sum+=len-j+1;
        }
        d[s[i]-'a']--;
    }
    return sum;
}

4.有效的快遞序列數目

【思路】用dp[i][j]表示當前收件爲i件,發件爲j件。當前的操作分爲收件和發件。

對於收件:dp[i][j]+=dp[i-1][j]*(n-(i-1));其中,收件可以是剩下包裹n-(i-1)中的任意一件

對於發件:dp[i][j]+=dp[i][j-1]*(i-(j-1));其中,發件可以是當前收件i除去已發的j-1,剩餘i-(j-1)中任意一件

int countOrders(int n){
   long long i,j,dp[n+1][n+1];
    memset(dp,0,sizeof(dp));
   long long mod=1000000007;
    dp[0][0]=1;//已發0件,已收0件,方案爲1
    for(i=1;i<=n;i++){
        for(j=0;j<=i;j++){
//如果當前是收件,那麼收件可以是剩下包裹n-(i-1)中的任意一件
            dp[i][j]+=dp[i-1][j]*(n-(i-1));
            dp[i][j]%=mod;
//如果當前是發件,那麼發件可以是當前收件i除去已發的j-1,剩餘i-(j-1)中任意一件
            if(j>0)
            dp[i][j]+=dp[i][j-1]*(i-(j-1));
            dp[i][j]%=mod;
        }
    }
    return (int)dp[n][n];
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章