Python 我的Codekata解决方案提供了正确的解决方案,但在最终测试用例中遇到了性能问题

Python 我的Codekata解决方案提供了正确的解决方案,但在最终测试用例中遇到了性能问题,python,algorithm,numbers,Python,Algorithm,Numbers,我用python3完成了我的算法,在codewars.com上解决了一个“codekata”。()我的代码正确且快速地解决了初始测试用例。但是,当提交给最终测试时,代码会因为花费太长时间来解决给定任务而超时 最初,我将for循环的内容实现为一个名为“calculate\u oddness\u level”的分离函数。我发现这比在for循环中实现要慢一些,所以我就这么做了 我知道在for循环中执行while循环并不是最佳性能。我想了好几次如何避免这种情况。但是,我需要确定列表中每个奇数的“奇数”级

我用python3完成了我的算法,在codewars.com上解决了一个“codekata”。()我的代码正确且快速地解决了初始测试用例。但是,当提交给最终测试时,代码会因为花费太长时间来解决给定任务而超时

最初,我将for循环的内容实现为一个名为“calculate\u oddness\u level”的分离函数。我发现这比在for循环中实现要慢一些,所以我就这么做了

我知道在for循环中执行while循环并不是最佳性能。我想了好几次如何避免这种情况。但是,我需要确定列表中每个奇数的“奇数”级别。为了确定“级别”,需要一个循环,而且似乎比递归更快。因此,似乎除了在for循环中运行while循环之外,别无选择。然而,我通过立即将偶数指定为“奇数级别”0,消除了循环中的偶数

因此,我不知道如何才能在绩效方面取得任何显著的改进

def oddest(a):
        if len(a) == 0: return None
        list_of_oddness_levels = []
        for n in a:
                if n % 2 == 0:
                     list_of_oddness_levels.append(0)
                else :
                    level = 1
                    while True:
                        n = (n-1)/2
                        if n % 2 == 0 or n % 1 != 0:
                                break
                        else:
                                level += 1
                    list_of_oddness_levels.append(level)
                print("adding Level!")
        maximum = max(list_of_oddness_levels)
        index_of_maximum = list_of_oddness_levels.index(maximum)

        if list_of_oddness_levels.count(maximum) > 1:
                return None
        else:
                return a[index_of_maximum]
根据最初的测试用例,我的代码应该能够正确地解决任务。然而,它的运行速度似乎慢了很多,因为它在最终提交时遇到了超时错误

我知道,可能会有一些简单的数学解决方案或5行高级代码利用一些python3库或我不知道的特殊函数。但是,最好采用详细、循序渐进且尽可能具有描述性的“干净代码”解决方案。

  • 您不需要列表,您可以使用O(1)个额外空间来完成

  • 问题可能不是您的实现,而是-1。为什么?它是无限奇数,因为(-1-1)/2=-1。有趣的是,这是唯一一个这样的数字,所有其他的负数都有一个奇怪的级别1

  • 对于正数,基本上是从右侧开始计算设置为1的连续位数,因此可以更快地使用掩码

假设32位整数(抱歉,Java),这就是这样一个实现的样子:

公共整数奇数(int[]a){
如果(a==null | | a.length==0)
返回null;
//创建所需的31个掩码,最左边的位仅设置为负数
int[]掩码=新int[31];
掩码[0]=1;
对于(int i=1;i<31;i++)
掩码[i]=(掩码[i-1]>1;
if(n个掩码[mid]==掩码[mid])
左=中;
其他的
右=中;
}
级别=右侧;
}
}
如果(级别>最佳级别){
最佳数=n;
最佳水平=水平;
冲突=错误;
}else if(level==bestLevel&&n!=bestNumber){
冲突=真实;
}
}
如果(冲突)
返回null;
返回最佳编号;
}

在代码中使用可能会有所帮助。感谢您的时间、提示和代码示例。问题确实是“-1”。我刚刚解决了这个问题,将任何数字的奇怪度级别在某个点上降到-1,并将其指定为“999”。此时,最终的测试用例完成得相当快。
public Integer oddest(int[] a) {
    if (a == null || a.length == 0)
        return null;
    // create the 31 masks needed, the left-most bit is only set for negative numbers
    int[] masks = new int[31];
    masks[0] = 1;
    for (int i = 1; i < 31; i++)
        masks[i] = (masks[i - 1] << 1) | 1; // masks[i - 1] * 2 + 1
    int bestNumber = 0;
    int bestLevel = 0;
    boolean conflict = true;
    for (int n : a) {
        int level = 0;
        if (n == -1) {
            return -1;
        } else if (n & 1 == 1) { // number is odd
            if (n < 0) {
                level = 1;
            } else {
                // now use the masks and bisection to find the oddity of positive numbers
                int left = 0; // finally at the index of best matching mask
                int right = 31; // never reached, finally left + 1
                while (left + 1 < right) {
                    int mid = (left + right) >> 1;
                    if (n & masks[mid] == masks[mid])
                        left = mid;
                    else
                        right = mid;
                }
                level = right;
            }
        }
        if (level > bestLevel) {
            bestNumber = n;
            bestLevel = level;
            conflict = false;
        } else if (level == bestLevel && n != bestNumber) {
            conflict = true;
        }
    }
    if (conflict)
        return null;
    return bestNumber;
}