[LeetCode] Friends Of Appropriate Ages 適合年齡段的朋友


 

Some people will make friend requests. The list of their ages is given and ages[i] is the age of the ith person. 

Person A will NOT friend request person B (B != A) if any of the following conditions are true:

  • age[B] <= 0.5 * age[A] + 7
  • age[B] > age[A]
  • age[B] > 100 && age[A] < 100

Otherwise, A will friend request B.

Note that if A requests B, B does not necessarily request A.  Also, people will not friend request themselves.

How many total friend requests are made?

Example 1:

Input: [16,16]
Output: 2
Explanation: 2 people friend request each other.

Example 2:

Input: [16,17,18]
Output: 2
Explanation: Friend requests are made 17 -> 16, 18 -> 17.

Example 3:

Input: [20,30,100,110,120]
Output: 
Explanation: Friend requests are made 110 -> 100, 120 -> 110, 120 -> 100.

 

Notes:

  • 1 <= ages.length <= 20000.
  • 1 <= ages[i] <= 120.

 

這道題是關於好友申請的,說是若A想要加B的好友,下面三個條件一個都不能滿足才行:

1. B的年齡小於等於A的年齡的一半加7。

2. B的年齡大於A的年齡。

3. B大於100歲,且A小於100歲。

實際上如果你仔細看條件3,B要是大於100歲,A小於100歲,那么B一定大於A,這就跟條件2重復了,完全不懂出題者的想法。不管了,強行解題唄。那么由於只能給比自己小的人發送好友請求,那么博主就想到我們可以獻給所有人拍個序,然后從后往前遍歷,對於每個遍歷到的人,再遍歷所有比他小的人,這樣第二個條件就滿足了,前面說了,第三個條件可以不用管了,那么只要看滿足第一個條件就可以了,還有要注意的,假如兩個人年齡相同,那么滿足了前兩個條件后,其實是可以互粉的,所以要額外的加1,這樣才不會漏掉任何一個好友申請,參見代碼如下:

 

解法一:

class Solution {
public:
    int numFriendRequests(vector<int>& ages) {
        int res = 0, n = ages.size();
        sort(ages.begin(), ages.end());
        for (int i = n - 1; i >= 1; --i) {
            for (int j = i - 1; j >= 0; --j) {
                if (ages[j] <= 0.5 * ages[i] + 7) continue;
                if (ages[i] == ages[j]) ++res;
                ++res;
            }
        }
        return res;
    }
};

 

我們可以來優化一下上面的解法,根據上面的分析,其實題目給的這三個條件可以歸納成一個條件,若A想加B的好友,那么B的年齡必須在 (A*0.5+7, A] 這個范圍內,由於區間要有意義的話,A*0.5+7 < A 必須成立,解出 A > 14,那么A最小就只能取15了。意思說你不能加小於15歲的好友(青少年成長保護???)。我們的優化思路是對於每一個年齡,我們都只要求出上面那個區間范圍內的個數,就是符合題意的。那么既然是求區域和,建立累加數組就是一個很好的選擇了,首先我們先建立一個統計數組numInAge,范圍是[0, 120],用來統計在各個年齡點上有多少人,然后再建立累加和數組sumInAge。這個都建立好了以后,我們就可以開始遍歷,由於之前說了不能加小於15的好友,所以我們從15開始遍歷,如果某個年齡點沒有人,直接跳過。然后就是統計出 (A*0.5+7, A] 這個范圍內有多少人,可以通過累計和數組來快速求的,由於當前時間點的人可以跟這個區間內的所有發好友申請,而當前時間點可能還有多人,所以二者相乘,但由於我們但區間里還包括但當前年齡點本身,所以還要減去當前年齡點上的人數,參見代碼如下:

 

解法二:

class Solution {
public:
    int numFriendRequests(vector<int>& ages) {
        int res = 0;
        vector<int> numInAge(121), sumInAge(121);
        for (int age : ages) ++numInAge[age];
        for (int i = 1; i <= 120; ++i) {
            sumInAge[i] = numInAge[i] + sumInAge[i - 1];
        }
        for (int i = 15; i <= 120; ++i) {
            if (numInAge[i] == 0) continue;
            int cnt = sumInAge[i] - sumInAge[i * 0.5 + 7];
            res += cnt * numInAge[i] - numInAge[i];
        }
        return res;
    }
};

 

參考資料:

https://leetcode.com/problems/friends-of-appropriate-ages/

https://leetcode.com/problems/friends-of-appropriate-ages/discuss/127341/10ms-concise-Java-solution-O(n)-time-and-O(1)-space

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM