5642. 大餐計數之哈希O(1)

提示:文章寫完後,目錄可以自動生成,如何生成可參考右邊的幫助文檔


前言

  1. 大餐計數之哈希O(1)

一、5642. 大餐計數之哈希O(1)

大餐 是指 恰好包含兩道不同餐品 的一餐,其美味程度之和等於 2 的冪。

你可以搭配 任意 兩道餐品做一頓大餐。

給你一個整數數組 deliciousness ,其中 deliciousness[i] 是第 i​​​​​​​​​​​​​​ 道餐品的美味程度,返回你可以用數組中的餐品做出的不同 大餐 的數量。結果需要對 109 + 7 取餘。

注意,只要餐品下標不同,就可以認爲是不同的餐品,即便它們的美味程度相同。

示例 1:

輸入:deliciousness = [1,3,5,7,9]
輸出:4
解釋:大餐的美味程度組合爲 (1,3) 、(1,7) 、(3,5) 和 (7,9) 。
它們各自的美味程度之和分別爲 4 、8 、8 和 16 ,都是 2 的冪。
示例 2:



輸入:deliciousness = [1,1,1,3,3,3,7]
輸出:15
解釋:大餐的美味程度組合爲 3 種 (1,1) ,9 種 (1,3) ,和 3 種 (1,7) 。

提示:

1 <= deliciousness.length <= 105
0 <= deliciousness[i] <= 220
通過次數2,097提交次數11,846

二、 程序

1,會超時的哦

struct arrays
{
   
    
    int value;
    int count;
}arrays;

struct hashmap
{
   
    
    struct arrays* table;
     long long used;
     long long size;
    
}hashmap;


bool Surplus(long long value)
{
   
    
    int count = 0;
    
    while (value>0 && count == 0)
    {
   
    
        if (value&1)
        {
   
    
            ++count;
        }
        value = value>>1;
    }
    if (value>0)
    {
   
    
        return false;
    }
    return count == 1;
}




int countPairs1(int* deliciousness, int deliciousnessSize)
{
   
    
    struct hashmap *map_ptr = malloc(sizeof(struct hashmap));
    map_ptr->size = deliciousnessSize;
    map_ptr->used = 0;
    
    map_ptr->table = malloc(sizeof(struct arrays) * deliciousnessSize);
   
    
    for (int i = 0; i < deliciousnessSize; ++i)
    {
   
    
        map_ptr->table[i].count = 0;
        bool find = false;
        int index = -1;
        for (int j = 0; j < map_ptr->used; ++j)
        {
   
    
            if (map_ptr->table[j].value == deliciousness[i])
            {
   
    
                ++map_ptr->table[j].count;
                find = true;
                break;
            }
            else if (map_ptr->table[j].value> deliciousness[i])
            {
   
    
                index = j;
                ++map_ptr->used;
                for (int w = map_ptr->used ; w >j; --w)
                {
   
    
                    map_ptr->table[w].value = map_ptr->table[w-1].value;
                    map_ptr->table[w].count = map_ptr->table[w-1].count;
                }
                
                    
                break;
            }
        }
        if (!find)
        {
   
    
            
            if (index != -1)
            {
   
    
                map_ptr->table[index].count = 1;
                map_ptr->table[index].value = deliciousness[i];
            }
            else 
            {
   
    
                map_ptr->table[map_ptr->used].count = 1;
                map_ptr->table[map_ptr->used].value = deliciousness[i];
                ++map_ptr->used;
            }
            
        }
    }
    int count = 0;
    for (int i = 0;i < map_ptr->used; ++i)
    {
   
    
        for (int j = i; j <  map_ptr->used; ++j)
        {
   
    
            if (i !=j)
            {
   
    
                
                if (Surplus(map_ptr->table[i].value + map_ptr->table[j].value))
                {
   
    
                    count += map_ptr->table[i].count * map_ptr->table[j].count;
                } 
            }
            else if (map_ptr->table[i].count>1)
            {
   
    
                if (Surplus(map_ptr->table[i].value + map_ptr->table[j].value))
                {
   
    
                    count += ((map_ptr->table[i].count-1) * map_ptr->table[i].count) /2; //等差數列
                } 
            }       
        }
    }
    if(map_ptr)
    {
   
    
		if(map_ptr->table)
		{
   
    
			free(map_ptr->table);
		}
		free(map_ptr);
	}
    long M = 1000000007;
    return count%M;
}

2,利用目標2的冪技巧

①, 這邊爲什麼是22呢是因爲 2 21 2^{21} 221是最大值

在這裏插入圖片描述

②,比如: 1和什麼數相加是2的冪

在這裏插入圖片描述

那可以把這些數放到哈希表中查詢的時間複雜度就是 O ( 1 ) O(1) O(1)

③,科學計數法

1.什麼是 1 e 9 1e9 1e9

通常來說這是計算機中一種科學計數法的表示形式:
1 e 9 = 1 ∗ 1 0 9 = 1000000000 ; 1e9 = 1*10^9 = 1000000000; 1e9=1109=1000000000
例如: 9 e 8 = 9 ∗ 1 0 8 = 900000000 ; 9e8 = 9*10^8 = 900000000; 9e8=9108=900000000
e表示10,e後面的數字表示次方,e的多少次方。


2.C++中的 1 e 9 1e9 1e9

int n u m 1 = 1 e 9 ; { num1 = 1e9;} num1=1e9;
int n u m 1 = 1 e 10 ; {num1 = 1e10;} num1=1e10;
輸出的結果爲:
num1 = 1 000 000 000;
num2 = 1 410 065 408;



那麼問題來了,爲什麼num2 不等於 10000000000 ?
C/C++中int類型是32位的,範圍是-2147483648 到 2147483647。
int佔用4個字節,也就是32位,除了第一位代表符號,剩下的31位可用。
十進制的 1e10時,轉換爲二進制:
10 0101 0100 0000 1011 1110 0100 0000 0000前兩位出現數據溢出問題。
而0101 0100 0000 1011 1110 0100 0000 0000 轉換成十進制就是 1 410 065 408




int countPairs(int* deliciousness, int deliciousnessSize)
{
   
    
        const int M = 1e9 + 7;
        int hash[3000000]={
   
    0}; //2的陪數 的差距保存哈希表
        long long ans = 0;
        for(int i = 0;i < deliciousnessSize; ++i)
        {
   
    
            //剛剛好是2的倍數
            ans += hash[deliciousness[i]];
            //距離 2的冪的距離統計個數 --》 這邊爲什麼是22呢是因爲2^21是最大值
            for(int j = 0; j < 22; j++)
            {
   
    
                if(((1<<j)-deliciousness[i])>=0) 
                {
   
    
                    hash[(1<<j)-deliciousness[i]]++;
                }
            }
        }
        return ans % M;
}

時間複雜度 O ( 21 ∗ N ) O(21*N) O(21N)
空間複雜度 O ( 3000000 ) O(3000000) O(3000000)

總結

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