ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

LeetCode题解(1681):最小不兼容性(Python)

2021-01-07 23:29:16  阅读:305  来源: 互联网

标签:sort Python 题解 self i2 j1 1681 i1 res


题目:原题链接(困难)

标签:贪心算法、动态规划

解法时间复杂度空间复杂度执行用时
Ans 1 (Python)44ms (99.08%)
Ans 2 (Python)
Ans 3 (Python)

解法一:

class Solution:
    def __init__(self):
        self.size = 0
        self.k = 0
        self.ans = 256

    def minimumIncompatibility(self, nums: List[int], k: int) -> int:
        # 处理无法分配的情况
        if collections.Counter(nums).most_common(1)[0][1] > k:
            return -1

        nums.sort()

        # 处理k为1的情况
        if k == 1:
            return nums[-1] - nums[0]

        # print("初始数组:", nums)

        # 计算每个子集的元素数
        self.k = k
        self.size = len(nums) // k

        # 生成初始情况
        res = []
        for i in range(0, len(nums), self.size):
            res.append(nums[i:i + self.size])

        self.count1(copy.deepcopy(res))

        return self.ans

    def count1(self, res):
        """将数组替换为无重复的情况(不一定是最优解)"""
        # print("初始数组:", res)

        has_same = False

        for i1 in range(self.k):
            sames = self.get_same(res[i1])
            for j1 in sames:
                has_same = True
                n1 = res[i1][j1]

                # 定义备选值
                ii1, jj1 = -1, -1
                ii2, jj2 = -1, -1

                # 向左寻找可替换的值
                i2 = i1 - 1
                while ii1 == -1 and i2 >= 0:
                    if n1 not in res[i2]:
                        for j2 in range(self.size - 1, -1, -1):
                            n2 = res[i2][j2]
                            if n2 not in res[i1]:
                                ii1, jj1 = i2, j2  # 填写备选情况
                                break
                    i2 -= 1

                # 向右寻找可替换的值
                i2 = i1 + 1
                while ii2 == -1 and i2 < self.k:
                    if n1 not in res[i2]:
                        for j2 in range(self.size):
                            n2 = res[i2][j2]
                            if n2 not in res[i1]:
                                ii2, jj2 = i2, j2  # 填写备选情况
                                break
                    i2 += 1

                # print(res, i1, "备选方案:", (ii1, jj1), (ii2, jj2))

                if ii1 != -1 and ii2 != -1:
                    res1 = copy.deepcopy(res)
                    res1[i1][j1], res1[ii1][jj1] = res1[ii1][jj1], res1[i1][j1]
                    res1[i1].sort()
                    res1[ii1].sort()
                    self.count1(res1)

                    res2 = copy.deepcopy(res)
                    res2[i1][j1], res2[ii2][jj2] = res2[ii2][jj2], res2[i1][j1],
                    res2[i1].sort()
                    res2[ii2].sort()
                    self.count1(res2)
                    return
                elif ii2 != -1:
                    res[i1][j1], res[ii2][jj2] = res[ii2][jj2], res[i1][j1]
                    res[i1].sort()
                    res[ii2].sort()
                elif ii1 != -1:
                    res[i1][j1], res[ii1][jj1] = res[ii1][jj1], res[i1][j1]
                    res[i1].sort()
                    res[ii1].sort()

        if not has_same:
            self.count2(copy.deepcopy(res))
        else:
            self.count1(copy.deepcopy(res))

    def count2(self, res):
        """将无重复的数组替换为最优解"""

        # print("符合数组:", res)

        for i1 in range(self.k):
            for j1 in range(self.size):
                n1 = res[i1][j1]

                # 向右寻找可交换的值
                i2 = i1 + 1
                while i2 < self.k:
                    if n1 not in res[i2]:
                        j2 = 0
                        n2 = res[i2][j2]
                        if n2 not in res[i1]:
                            # 条件允许交换,考虑交换是否值得
                            min1_old, max1_old = res[i1][0], res[i1][-1]
                            min2_old, max2_old = res[i2][0], res[i2][-1]

                            temp = copy.copy(res[i1])
                            temp.remove(n1)
                            temp.append(n2)
                            temp.sort()
                            min1_new, max1_new = temp[0], temp[-1]

                            temp = copy.copy(res[i2])
                            temp.remove(n2)
                            temp.append(n1)
                            temp.sort()
                            min2_new, max2_new = temp[0], temp[-1]

                            change1 = (max1_new - min1_new) - (max1_old - min1_old)
                            change2 = (max2_new - min2_new) - (max2_old - min2_old)

                            if change1 + change2 < 0:
                                # print(res, (i1, j1), "<-替换->", (i2, j2))

                                res[i1][j1], res[i2][j2] = res[i2][j2], res[i1][j1]
                                res[i1].sort()
                                res[i2].sort()

                                return self.count2(res)

                    i2 += 1

        # 没有更换则计算最优结果
        else:
            # print("最终数组:", res)
            ans = 0
            for i in range(self.k):
                ans += res[i][-1] - res[i][0]
            self.ans = min(self.ans, ans)

    @staticmethod
    def get_same(lst):
        sets = set()
        res = []
        for i in range(len(lst)):
            if lst[i] not in sets:
                sets.add(lst[i])
            else:
                res.append(i)
        return res

标签:sort,Python,题解,self,i2,j1,1681,i1,res
来源: https://blog.csdn.net/Changxing_J/article/details/112137897

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有