力扣----排序

题目

  1. 977. 有序数组的平方
  2. 268. 丢失的数字
  3. 1877. 数组中最大数对和的最小值
  4. 950. 按递增顺序显示卡牌
  5. 1464. 数组中两元素的最大乘积
  6. 1636. 按照频率将数组升序排序
  7. 1287. 有序数组中出现次数超过25%的元素
  8. 436. 寻找右区间

解题思路与代码详情

【题1】977. 有序数组的平方

977. 有序数组的平方: 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

题目解析: 求由给定数组中元素的平方形成的新数组,并按升序顺序排列。
解题思路: 遍历数组元素求平方,进行排序。

# python3
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        n=len(nums)
        ret=[0]*n
        for i in range(n):
            ret[i]=(nums[i])*(nums[i])
        ret.sort()
        return ret
//C
int cmp(const void *p1, const void *p2) {
    return *(int*)p1-*(int*)p2;
}
int* sortedSquares(int* nums, int numsSize, int* returnSize){
    *returnSize = numsSize;
    int* ret = (int*)malloc(sizeof(int)*numsSize);
    for(int i=0;i<numsSize;i++){
        ret[i]=nums[i]*nums[i];
    }
    qsort(ret, numsSize, sizeof(int), cmp);
    return ret;
    free(ret);
}

【题2】268. 丢失的数字

268. 丢失的数字: 给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

题目解析: 数组中的元素由该数组长度内的自然整数构成,同时数组中包含整数0,所以题中数组是由0到数组长度(假设为n)这 n + 1 n+1 n+1个整数中的 n n n个整数组成,需要找出这 n + 1 n+1 n+1个整数中没在数组中的那一个元素。
解题思路: 方法1:遍历数组中元素,如果元素不是数组中元素,则返回;若遍历完未找到缺失元素,则缺失元素为数组长度。方法2:先排序再查找。

#python3
#暴力查找
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        n=len(nums)
        ret=0
        for i in range(n+1):
            if i not in nums:
               ret=i
        return ret
#先排序再查找
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        n=len(nums)
        nums.sort()
        for i in range(n):
            if i!=nums[i]:
               return i
        return n
//C
int cmp(const void* p1, const void* p2){
    return *(int*)p1-*(int*)p2;
}
int missingNumber(int* nums, int numsSize){
    qsort(nums, numsSize, sizeof(int), cmp);
    for(int i=0;i<numsSize;i++){
        if(i!=nums[i]){
            return i;
        }
    }
    return numsSize;
}

【题3】1877. 数组中最大数对和的最小值

1877. 数组中最大数对和的最小值: 一个数对 (a,b) 的 数对和 等于 a + b 。最大数对和 是一个数对数组中最大的 数对和

比方说,如果我们有数对 (1,5) ,(2,3) 和 (4,4),最大数对和为 max(1+5, 2+3, 4+4) = max(6, 5, 8) = 8 。

给你一个长度为 偶数 n 的数组 nums ,请你将 nums 中的元素分成 n / 2 个数对,使得:

nums 中每个元素 恰好 在 一个 数对中,且
最大数对和 的值 最小

请你在最优数对划分的方案下,返回最小的 最大数对和

题目解析: 数组中元素两两组成数对,求最小的最大数对和。
解题思路: 对数组元素进行升序排序,最小元素与最大元素构成数对,次小元素与次优元素构成数对,以此类推,从而产生最小的数对和,从所构成的数对和中选择最大值。

#python3
class Solution:
    def minPairSum(self, nums: List[int]) -> int:
        n=len(nums)
        nums.sort()
        #ret=[0]*(n//2)
        maxret=-1
        for i in range(n//2):
            #ret.append(nums[i]+nums[n-1-i])
            #ret[i]=nums[i]+nums[n-1-i]
            maxret=max(maxret,nums[i]+nums[n-1-i])
        return maxret
        #return max(ret)
//C
int cmp(const void* p1, const void* p2){
    return *(int*)p1-*(int*)p2;
}
int minPairSum(int* nums, int numsSize){
    int max = 0;
    qsort(nums, numsSize, sizeof(int), cmp);
    for(int i=0;i<numsSize/2;i++){
        max=fmax(max,nums[i]+nums[numsSize-1-i]);
    }
    return max;
}

【题4】950. 按递增顺序显示卡牌

950. 按递增顺序显示卡牌: 牌组中的每张卡牌都对应有一个唯一的整数。你可以按你想要的顺序对这套卡片进行排序。

最初,这些卡牌在牌组里是正面朝下的(即,未显示状态)。

现在,重复执行以下步骤,直到显示所有卡牌为止:

1.从牌组顶部抽一张牌,显示它,然后将其从牌组中移出。
2.如果牌组中仍有牌,则将下一张处于牌组顶部的牌放在牌组的底部。
3.如果仍有未显示的牌,那么返回步骤 1。否则,停止行动。

返回能以递增顺序显示卡牌的牌组顺序。

答案中的第一张牌被认为处于牌堆顶部。

题目解析: 求能使卡牌按升序顺序显示出来的卡牌放置顺序。
解题思路: 模拟抓牌过程。 以样例 [17,13,11,2,3,5,7] 为例,首先将数组元素升序排列得到[2,3,5,7,11,13,17] ,然后将排序后的数组元素依次按下列操作重新放置。
在这里插入图片描述

#python3
class Solution(object):
    def deckRevealedIncreasing(self, deck):
        '''
        创建双向队列
        import collections
        d = collections.deque()  
        '''
        n = len(deck)
        deck.sort()
        index = collections.deque(range(n))#生成序号
        ret = [0] * n
        for card in deck:
            ret[index.popleft()] = card
            #popleft(获取最左边一个元素,并在队列中删除)间隔排放元素
            if index:
                index.append(index.popleft())
        return ret
//C
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int cmp(const void* p1, const void* p2){
    return *(int*)p1-*(int*)p2;
}
int* deckRevealedIncreasing(int* deck, int deckSize, int* returnSize){
    *returnSize = deckSize;
    int* ret = (int*)malloc(sizeof(int)*deckSize);
    int* index = (int*)malloc(sizeof(int)*deckSize);
    qsort(deck, deckSize, sizeof(int), cmp);

    for(int i=0;i<deckSize;i++){
        index[i]=i;
    }

    for(int i=1;i<deckSize;i++){
        index[i-1]=index[i-1];
        int temp = index[i];
        for(int j=i;j<deckSize-1;j++){
            index[j]=index[j+1];
        }
        index[deckSize-1]=temp;
    }
        
    for(int i=0;i<deckSize;i++){
        ret[index[i]]=deck[i];
    }
    return ret;
    free(ret);
    free(index);
}

【题5】1464. 数组中两元素的最大乘积

1464. 数组中两元素的最大乘积: 给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。
请你计算并返回该式的最大值。

题目解析: 求数组中两个较大元素减一后的乘积。
解题思路: 排序求积。

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        #n=len(nums)
        nums.sort(reverse=1)
        return (nums[0]-1)*(nums[1]-1)
int cmp(const void* p1, const void* p2){
    return *(int*)p2-*(int*)p1;
}

int maxProduct(int* nums, int numsSize){
    qsort(nums, numsSize, sizeof(int),cmp);
    return (nums[0]-1)*(nums[1]-1);
}

【题6】1636. 按照频率将数组升序排序

1636. 按照频率将数组升序排序: 给你一个整数数组 nums ,请你将数组按照每个值的频率 升序 排序。如果有多个值的频率相同,请你按照数值本身将它们 降序 排序。

请你返回排序后的数组。

**题目解析:**以输出频率从多到少输出数组元素。
**解题思路:**对数组元素同时按频率升序,数值降序顺序输出。

class Solution:
    def frequencySort(self, nums: List[int]) -> List[int]:
        return sorted(nums, key=lambda x: (nums.count(x), -x))

【题7】1287. 有序数组中出现次数超过25%的元素

1287. 有序数组中出现次数超过25%的元素: 给你一个非递减的 有序 整数数组,已知这个数组中恰好有一个整数,它的出现次数超过数组元素总数的 25%。
请你找到并返回这个整数。

题目解析: 找出出现次数超过总数25%的那个唯一元素。
解题思路: 排序,累积次数。

class Solution:
    def findSpecialInteger(self, arr: List[int]) -> int:
        n=len(arr)
        #listarr=collections.Counter(arr)
        ret=sorted(arr,key=lambda x:(arr.count(x)))
        #ret=sorted(arr, key=lambda x: (arr.count(x), -x))
        return ret[n-1]
        #for value in listarr:
            #if listarr[value]*100//n>25:
               # return value

【题8】436. 寻找右区间

436. 寻找右区间: 给你一个区间数组 intervals ,其中 intervals[i] = [starti, endi] ,且每个 starti 都 不同

区间 i 的 右侧区间 可以记作区间 j ,并满足 startj >= endi ,且 startj 最小化

返回一个由每个区间 i 的 右侧区间 在 intervals 中对应下标组成的数组。如果某个区间 i 不存在对应的 右侧区间 ,则下标 i 处的值设为 -1
题目解析: 每个区间的y坐标同其他区间的x坐标相比较,其他区间中存在x坐标值大于该区间的y坐标值,找出符合要求的最小的其他区间的x坐标值,若存在这样的x坐标值,返回该x坐标值的小区间的索引值,若找不到,返回-1.
解题思路: 排序+二分。按所有区间内的x坐标值的大小排序取索引值,如果小区间的y坐标值大于x坐标的最大值或小于x坐标最小值,那么返回-1,二分查找最接近当前区间的y坐标值的x坐标的索引值。

#法1超时
class Solution:
    def findRightInterval(self, intervals: List[List[int]]) -> List[int]:
        n=len(intervals)
        ret=[0]*n
        if n==1:
            ret[0]=-1
            return ret
        else:
            for i in range(n):#遍历每个区间
                mins=10000
                for j in range(n):
                    if j==i:
                        continue
                    if intervals[j][0]>=intervals[i][1]:
                        mins = min(mins, intervals[j][0])
                        if mins == intervals[j][0]:
                            ret[i]=j
                            #print(temp)
                if mins==10000:
                    ret[i]=-1
        return ret
#排序+二分
class Solution:
    def findRightInterval(self, intervals: List[List[int]]) -> List[int]:
        n = len(intervals)
        s = sorted(range(n), key=lambda x: intervals[x][0])
        ans = []
        minx, maxx = intervals[s[0]][0], intervals[s[n-1]][0]
        for x, y in intervals:
            if y < minx or y > maxx:
                ans.append(-1)
            else:
                left, right = 0, n - 1
                while left < right:
                    mid = (left + right) // 2
                    if y > intervals[s[mid]][0]:
                        left = mid + 1
                    else:
                        right = mid
                ans.append(s[left])
        return ans

参考文献

  1. https://blog.csdn.net/WhereIsHeroFrom/article/details/124550030
  2. https://blog.csdn.net/WhereIsHeroFrom/article/details/125109551
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值