title: LeetCode922奇偶数组排列——细想与逻辑 date: 2019-02-28 11:37:15 tags: LeetCode系列
LeetCode922:奇偶数组排列——细想与逻辑
LeetCode的922题目是:
给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。
对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。
你可以返回任何满足上述条件的数组作为答案。
示例: 输入: [4,2,5,7] 输出: [4,5,2,7] 解释: [4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
先说说这个题的解法和三个思路,然后我再讲讲从这个题延伸的思路和做事的是的原则
基础版本:
class Solution:
def sortArrayByParityII(self, A: 'List[int]') -> 'List[int]':
even,odd=[],[]
result=[]
for n in A:
if n%2==0:#如果是偶数
even.append(n)
else:#如果是奇数
odd.append(n)
while odd and even:#交替排列
result.append(even.pop())
result.append(odd.pop())
return result
分析&解题: 通过题目我可知,数组最终排列的是偶数和奇数交替排列,所以我们最开始想的就是,把一个混乱的数组以奇数和偶数的队列分开,然后我们把偶数列表和奇数列表里面的数交替放到最终返回结果的那个列表里面。 这样做比较直观,我们打题目做了分解,先区分再合并。
进阶I:
class Solution:
def sortArrayByParityII(self, A: 'List[int]') -> 'List[int]':
i,j=0,1
while i<len(A): #防止越界: i的最大值在len(A)-1。因为我们倒数第二个是偶数。
if A[i]%2!=0:
while A[j]%2!=0:
j+=2
A[i],A[j]=A[j],A[i]#将i号位和j号位做了替换
i+=2
return A
分析&解题: 在原有的队列中,一开始我们设置一号位和二号位(i=0,j=1),我们从一号位遍历这个数组,如果偶数位不是偶数,我就在奇数位去找偶数,然后找到奇数位的偶数,我将前面偶数位的奇数和奇数位的偶数调换(ps;这里的调换语句——>A[i],A[j]=A[j],A[i]). 这里我们i+=2和j+=2是因为,我i代表偶数位,j代表奇数位,所以我们+2是为了保证i都为偶数,j都为奇数。
进阶II:
class Solution:
def sortArrayByParityII(self, A: 'List[int]') -> 'List[int]':
i,j=0,1
list=[0]*len(A)
for n in A:
if n&1==0:
list[i]=n
i+=2
else:
list[j]=n
j+=2
return list
分析&解题: 我们先创造一个长度为len(A)的队列list,里面的而数据以0填满。遍历原有队列A,里面如果是奇数,就让这个数进入list的奇数位,如果这个数为偶数,就让这个数进入list的偶数位。 里面判断奇偶数的方法是(n&1),符号&是一个位运算,如果是偶数: n&1==0,,如果是奇数:n&1!=0。
算法思路和做事原则
这个题目的思路其实比较简单,就是把奇数和偶数交叉排列,所以一开始的想打就是先分组,再合并。但是这有一个问题就是我们做了很多的重复性工作,算法的复杂度会很高。进阶的算法思路是: 减少分组和合并的步骤,直接盯着偶数位去看,如果偶数位不是偶数,那么我们就说明奇数位中一定有一个是是偶数,所以我把这两个交换一下,则改变原来的列表就好。第二个进阶的方法是,先创建一个新列表list,我们遍历原列表,如果是奇数我们就放在list的奇数位,如果是偶数,我们就放在list的偶数位,在这个算法中我们只创建了一个内存空间,遍历了一次列表,和基础算法比起来,简单了许多。 那么其实我们已经可以知道了,什么是好的算法,好的算法就是尽量少做事情。而我们做事的原则应该是,如果你是第一次在做这样的事情,你要先回基本的算法,它是你完成这样工作的基础(先得到60分),但是很耗时间和空间,因为他是复杂的算法,当你持续了解这个题目或者你做的事情,你的要想想如何才能少做事情,尽可能的降低时间和空间的使用,得到一个好算法(达到80——90分)。其中参考其他的方法,并且理解他的思路,这个很重要。 下一次我在聊聊大局和细节的关系。