荷兰国旗问题python_01-时间复杂度、对数器(python)、冒泡、选择、递归实质、归并、小和问题、逆序对、mid...

java版本

packagebasic_class_01;importjava.util.Arrays;public classCode_02_SelectionSort {public static void selectionSort(int[] arr) {if (arr == null || arr.length < 2) {return;

}for (int i = 0; i < arr.length - 1; i++) {int minIndex =i;for (int j = i + 1; j < arr.length; j++) {

minIndex= arr[j] < arr[minIndex] ?j : minIndex;

}

swap(arr, i, minIndex);

}

}public static void swap(int[] arr, int i, intj) {int tmp =arr[i];

arr[i]=arr[j];

arr[j]=tmp;

}

}

python版本

#选择排序#时间复杂度O(N^2)#空间复杂度O(1)

defselection_sort(li):if li is None and len(li) < 2:return

for i in range(len(li) - 1): #当前n-1个确定好了,最后一个就确定ok

min_index =ifor j in range(i + 1, len(li)):if li[j]

min_index=j

swap(li, i, min_index)returnlidefswap(data, i, j):

data[i]= data[i] ^data[j]

data[j]= data[i] ^data[j]

data[i]= data[i] ^data[j]#for test

ret = selection_sort([9, 2, 7, 8, 3, 2, 1])print(ret)

4、插入排序

插入排序的细节讲解与复杂度分析

时间复杂度O(N^2),额外空间复杂度O(1)

java版本

public static void insertionSort(int[] arr) {if (arr == null || arr.length < 2) {return;

}for (int i = 1; i < arr.length; i++) {for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {

swap(arr, j, j+ 1);

}

}

}public static void swap(int[] arr, int i, intj) {

arr[i]= arr[i] ^arr[j];

arr[j]= arr[i] ^arr[j];

arr[i]= arr[i] ^arr[j];

}

python版本

#插入排序#时间复杂度O(N^2)#空间复杂度O(1)

defselection_sort(li):if li is None and len(li) < 2:return

for i in range(1, len(li)):

temp=li[i]

j= i - 1

while j >= 0 and temp

li[j+ 1] = li[j] #元素往后推一个位置

j -= 1li[j+ 1] = temp #最小元素放在第一个位置

returnli#for test

ret = selection_sort([9, 2, 7, 8, 3, 2, 1])print(ret)

5、对数器

1、用途:验证算法是否正确的一种方式

2、使用

0,有一个你想要测的方法a,

1,实现一个绝对正确但是复杂度不好的方法b,

2,实现一个随机样本产生器

3,实现比对的方法

4,把方法a和方法b比对很多次来验证方法a是否正确。

5,如果有一个样本使得比对出错,打印样本分析是哪个方法出错

6,当样本数量很多时比对测试依然正确,可以确定方法a已经正确。

3、实现

1.随机数组发生器

2.准备一个绝对正确的方法

3.大样本测试 500 000

java版本

packagebasic_class_01;importjava.util.Arrays;public classCode_00_BubbleSort {//需要验证的算法??

public static void bubbleSort(int[] arr) {if (arr == null || arr.length < 2) {return;

}for (int e = arr.length - 1; e > 0; e--) {for (int i = 0; i < e; i++) {if (arr[i] > arr[i + 1]) {

swap(arr, i, i+ 1);

}

}

}

}public static void swap(int[] arr, int i, intj) {

arr[i]= arr[i] ^arr[j];

arr[j]= arr[i] ^arr[j];

arr[i]= arr[i] ^arr[j];

}//1.随机数组发生器//for test

public static int[] generateRandomArray(int maxSize, intmaxValue) {//Math.random() -> double [0,1)//(int) ((size+1)*Math.random()) -> [0,size] 整数//size = 6, size+1 = 7//Math.random() -> [0,1) * 7 -> [0,7) double//double -> int[0,6) -> int//生成长度随机的数组

int[] arr = new int[(int) ((maxSize + 1) *Math.random())];for (int i = 0; i < arr.length; i++) {

arr[i]= (int) ((maxValue + 1) * Math.random()) - (int) (maxValue *Math.random());

}returnarr;

}//2.准备一个绝对正确的方法//for test

public static void comparator(int[] arr) {

Arrays.sort(arr);

}//3.大样本测试 500 000//for test

public static voidmain(String[] args) {int testTime = 500000;int maxSize = 100;int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {int[] arr1 =generateRandomArray(maxSize, maxValue);int[] arr2 =copyArray(arr1);

bubbleSort(arr1);

comparator(arr2);if (!isEqual(arr1, arr2)) {

succeed= false;break;

}

}

System.out.println(succeed? "Nice!" : "Fucking fucked!");int[] arr =generateRandomArray(maxSize, maxValue);

printArray(arr);

bubbleSort(arr);

printArray(arr);

}//3.1 copy//for test

public static int[] copyArray(int[] arr) {if (arr == null) {return null;

}int[] res = new int[arr.length];for (int i = 0; i < arr.length; i++) {

res[i]=arr[i];

}returnres;

}//3.2 验证isEqual,长度一样,每位的数字一样//for test

public static boolean isEqual(int[] arr1, int[] arr2) {if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {return false;

}if (arr1 == null && arr2 == null) {return true;

}if (arr1.length !=arr2.length) {return false;

}for (int i = 0; i < arr1.length; i++) {if (arr1[i] !=arr2[i]) {return false;

}

}return true;

}//3.3 打印结果//for test

public static void printArray(int[] arr) {if (arr == null) {return;

}for (int i = 0; i < arr.length; i++) {

System.out.print(arr[i]+ " ");

}

System.out.println();

}

}

python版本

importrandom#我的方法

defbubble_sort(li):if li is None or len(li) < 2:returnlifor end in range(len(li) - 1, -1, -1):for i inrange(end):if li[i] > li[i + 1]:

swap(li, i, i+ 1)returnli#交换两个数字,与

defswap(data, i, j):

data[i]= data[i] ^data[j]

data[j]= data[i] ^data[j]

data[i]= data[i] ^data[j]'''for test'''

#1.随机数组发生器

defgenerate_random_array(max_size,max_vaule):

arr=[]

arr_len= int((max_size+1)*random.random()) #长度随机,不能大于max_size

for i inrange(arr_len):

arr.append(int((max_vaule+ 1) * random.random()) - int(max_vaule * random.random())) #value随机

returnarr#2.准备一个绝对正确的方法

defcomparator(arr):returnsorted(arr)#3.大样本测试 500 000

defmain():

test_time= 500max_size= 100max_value= 100succeed=Truefor i inrange(test_time):

arr1=generate_random_array(max_size,max_value)

arr2=copy_array(arr1)

arr1= bubble_sort(arr1) #我的方法

arr2 = comparator(arr2) #系统绝对正确的方法

if notis_equal(arr1,arr2):

succeed=Falsebreak

print("Nice") if succeed else print("Fucking fucked")

arr=generate_random_array(max_size,max_value)

print_array(arr)

bubble_sort(arr)

print_array(arr)#3.1 copy

defcopy_array(arr):if arr isNone:returnNone

res=[]for i inrange(len(arr)):

res.append(arr[i])returnres#3.2 验证isEqual,长度一样,每位的数字一样

defis_equal(arr1,arr2):if (arr1 is None and arr2 is not None) or (arr1 is not None and arr2 isNone):returnFalseif arr1 is None and arr2 isNone:returnTrueif len(arr1) !=len(arr2):returnFalsefor i inrange(len(arr1)):if arr1[i] !=arr2[i]:returnFalsereturnTrue#3.3 打印结果

defprint_array(arr):if arr isNone:return

for i inrange(len(arr)):print(arr[i],end=' ')print('\n')if __name__ == '__main__':

main()

6、递归

6.1 递归实质

剖析递归行为和递归行为时间复杂度的估算

一个递归行为的例子

defget_max(arr,left,right):if left ==right:returnarr[left]

mid= (left+right)//2max_left=get_max(arr,left,mid)

max_right= get_max(arr,mid+1,right)returnmax(max_left,max_right)

li= [4,3,2,1]

ret= get_max(li,0,len(li)-1)print(ret) #4

还原现场 ,系统栈

6.2 递归行为复杂度通式

master公式的使用

T(N) = a*T(N/b) + O(N^d)

1) log(b,a) > d -> 复杂度为O(N^log(b,a))

2) log(b,a) = d -> 复杂度为O(N^d * logN)

3) log(b,a) < d -> 复杂度为O(N^d)

补充阅读:www.gocalf.com/blog/algorithm-complexity-and-master-

theorem.html

7、归并排序(递归、分治)

归并排序的细节讲解与复杂度分析

时间复杂度O(N*logN),额外空间复杂度O(N)

java版本

public static void mergeSort(int[] arr) {if (arr == null || arr.length < 2) {return;

}

mergeSort(arr,0, arr.length - 1);

}public static void mergeSort(int[] arr, int l, intr) {if (l ==r) {return;

}int mid = l + ((r - l) >> 1);

mergeSort(arr, l, mid);

mergeSort(arr, mid+ 1, r);

merge(arr, l, mid, r);

}public static void merge(int[] arr, int l, int m, intr) {int[] help = new int[r - l + 1];int i = 0;int p1 =l;int p2 = m + 1;while (p1 <= m && p2 <=r) {

help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];

}while (p1 <=m) {

help[i++] = arr[p1++];

}while (p2 <=r) {

help[i++] = arr[p2++];

}for (i = 0; i < help.length; i++) {

arr[l+ i] =help[i];

}

}

python版本

defmergeSort(arr):if arr is None or len(arr) < 2:returnarr

merge_sort(arr,0,len(arr)-1)returnarrdefmerge_sort(arr,left,right):if left ==right:returnarr

mid= left + ((right-left)>>1) #left和right中点的位置 (L+R)//2

#分解

merge_sort(arr,left,mid) #T(n/2)

merge_sort(arr,mid+1,right) #T(n/2)

#合并

merge(arr,left,mid,right) #O(n)

#T(n) = 2T(N/2)+ O(N)

defmerge(arr,left,mid,right):

temp=[]

i,j= left,mid+1

while i<=mid and j <=right:if arr[i]

temp.append(arr[i])

i+= 1

else:

temp.append(arr[j])

j+=1

#两个必且有一个越界

while i<=mid:

temp.append(arr[i])

i+= 1

while j<=right:

temp.append(arr[j])

j+= 1arr[left:right+1] =temp

li= [3,1,2,4]

ret=mergeSort(li)print(ret)

时间复杂度估算

为什么归并排序比较快

其他排序,有很多无效的比较,浪费比较

8、小和问题

小和问题

在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组

的小和。

例子:

[1,3,4,2,5]

1左边比1小的数,没有;

3左边比3小的数,1;

4左边比4小的数,1、3;

2左边比2小的数,1;

5左边比5小的数,1、3、4、2;

所以小和为1+1+3+1+1+3+4+2=16

4*1 + 2*3 + 1*4 + 1*2

java版本

public static int smallSum(int[] arr) {if (arr == null || arr.length < 2) {return 0;

}return mergeSort(arr, 0, arr.length - 1);

}public static int mergeSort(int[] arr, int l, intr) {if (l ==r) {return 0;

}int mid = l + ((r - l) >> 1);return mergeSort(arr, l, mid) + mergeSort(arr, mid + 1, r) +merge(arr, l, mid, r);

}public static int merge(int[] arr, int l, int m, intr) {int[] help = new int[r - l + 1];int i = 0;int p1 =l;int p2 = m + 1;int res = 0;while (p1 <= m && p2 <=r) {

res+= arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;

help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];

}while (p1 <=m) {

help[i++] = arr[p1++];

}while (p2 <=r) {

help[i++] = arr[p2++];

}for (i = 0; i < help.length; i++) {

arr[l+ i] =help[i];

}returnres;

}

python版本

defsmall_sum(arr):if arr is None or len(arr) < 2:returnarrreturn merge_sort(arr, 0, len(arr) - 1)defmerge_sort(arr, l, r):if l ==r:#return arr 要进行res相加操作

return0

m= l + ((r - l) >> 1) #m = (L+R)//2

return merge_sort(arr, l, m) + merge_sort(arr, m + 1, r) +merge(arr, l, m, r)defmerge(arr, l, m, r):

temp=[]

i, j= l, m + 1res= 0 #每次merge产生的 小和

while i <= m and j <=r:

res+= (r - j + 1) * arr[i] if arr[i] < arr[j] else 0 #小和

if arr[i]

temp.append(arr[i])

i+= 1

else:

temp.append(arr[j])

j+= 1

#两个必且有一个越界

while i <=m:

temp.append(arr[i])

i+= 1

while j <=r:

temp.append(arr[j])

j+= 1

for i inrange(len(temp)):

arr[l+ i] =temp[i]returnres

arr= [1,3,4,2,5]print(small_sum(arr))

res += (r - j + 1) * arr[i] if arr[i] < arr[j] else 0 # 小和

  

左神语录

有一个思路要给大家贯彻到底的

所有东西都是技术问题

你写不出来的原因是因为缺乏练习,

而不是你这个人笨

你知道吗,真的是要建立这种信心

因为我就是那样的阶段趟过来的,

这其中的辛苦确实都知道

9、逆序对问题

在一个数组中,左边的数如果比右边的数大,则折两个数构成一个逆序对,请打印所有逆序

对。

10、取mid的几种方法

11、交换两个数的值

方法1:

tmp = arr[i];

arr[i] = arr[j];

arr[j] = tmp;

方法2:

arr[i] = arr[i] ^ arr[j];

arr[j] = arr[i] ^ arr[j];

arr[i] = arr[i] ^ arr[j];

Z、总结

1、时间复杂度

big O  代表常数操作

只要高阶项,不要低阶项,也不要高阶项的系数

2、冒泡

时间复杂度O(N^2)

额外空间复杂度O(1)

3、选择

时间复杂度O(N^2)

额外空间复杂度O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值