python 动态数组_数据结构python实现之动态数组

(一)Introduction

引入问题:找到丢失的数字

算法实现1:求和相减

算法实现2:异或运算

A^A=0

A^0=A

A^B=B^A

========================================

(1^2^3...x^...n)^

(1^2^3...0^...n)

---------------

0^0^0...x^...0=x

1. 时间复杂度与空间复杂度

O(1) < O(logn)

2. 主项定理

T(n):解决这个问题所花的时间

aT(n/b):每个大问题可以分解成a个小问题(所需要的小问题的个数),每个小问题的size为n/b

f(n):每一步的时间

二分法的主项公式:T(n) = T(n/2) + 1

归并排序:T(n) = 2T(n/2) + n

(二)Array

1. Array的应用

(1)洗牌

算法1:每次产生两张牌,任意交换其位置

def shuffle_1st(cards):

for k in range(len(cards)):

i = random.randint(0,len(cards)-1)

j = random.randint(0,len(cards)-1)

cards[i],cards[j] = cards[j],cards[i]

def test_shuffle(f):

results = [[0 for i in range(10)] for j in range(10)]

for i in range(10000):

A = [i for i in range(0,10)]

f(A)

print(A)

for j in range(len(A)):

results[A[j]][j] += 1

print('\n'.join([''.join(['{:6}'.format(item) for item in row])for row in results]))

test_shuffle(shuffle_1st)

----------------------------results--------------------------------------

1949 878 889 895 892 903 910 876 889 919

841 2051 846 931 839 945 887 856 884 920

930 881 2036 884 865 857 893 872 928 854

888 814 922 1979 940 894 891 882 893 897

865 896 901 891 1943 875 928 916 881 904

905 927 869 885 912 1911 904 902 890 895

900 857 895 911 921 931 1936 876 884 889

940 873 890 883 851 876 893 2010 886 898

894 902 890 859 915 848 876 879 2023 914

888 921 862 882 922 960 882 931 842 1910

明显对角线元素数量最多,也就是第i张牌在第i个位置的概率最大,显然并不是一个很好的洗牌算法。

算法2:每次产生一张牌i,让这张牌和第k次对应的第k张牌进行交换

def shuffle_2nd(cards):

for k in range(len(cards)):

i = random.randint(0,len(cards)-1)

cards[k],cards[i] = cards[i],cards[k]

def test_shuffle(f):

results = [[0 for i in range(10)] for j in range(10)]

for i in range(10000):

A = [i for i in range(0,10)]

f(A)

print(A)

for j in range(len(A)):

results[A[j]][j] += 1

print('\n'.join([''.join(['{:6}'.format(item) for item in row])for row in results]))

test_shuffle(shuffle_2nd)

----------------------------results--------------------------------------

995 982 1004 1018 1022 1039 1003 953 995 989

1264 956 906 939 979 909 992 1019 1008 1028

1148 1301 905 880 971 925 973 921 967 1009

1111 1156 1199 932 895 917 922 933 944 991

1095 1037 1185 1158 844 891 881 945 983 981

973 1029 1100 1141 1151 847 884 953 977 945

936 977 975 1038 1089 1204 858 930 995 998

842 879 953 1011 1093 1137 1230 895 971 989

806 889 904 964 973 1094 1177 1238 932 1023

830 794 869 919 983 1037 1080 1213 1228 1047

明显对角线元素数量最多少,也就是第i张牌在第i个位置的概率最小,显然并不是一个很好的洗牌算法。

算法3:

每次随机产生一张牌从本次循环靠后的一张牌,然后和本张牌进行交换,即每次之后自己以及自己之后的任意一张牌进行交换,每张牌在每个位置的概率为1/n

def shuffle_correct(cards):

for k in range(len(cards)):

randomi = random.randint(k,len(cards)-1)

cards[k],cards[randomi] = cards[randomi],cards[k]

def test_shuffle(f):

results = [[0 for i in range(10)] for j in range(10)]

for i in range(100000):

A = [i for i in range(0,10)]

f(A)

print(A)

for j in range(len(A)):

results[A[j]][j] += 1

print('\n'.join([''.join(['{:6}'.format(item) for item in row])for row in results]))

test_shuffle(shuffle_correct)

----------------------------results-----------------------------------------

9967 9951 9888 10069 10070 9963 9972 10031 10130 9959

9898 10034 10126 10102 10072 9948 9819 10007 9967 10027

9949 10009 9883 10009 9826 10074 9991 10047 9980 10232

10090 10063 10025 10070 9943 9886 10132 9832 9932 10027

10028 9933 9951 9991 9980 10205 10012 9790 10061 10049

10099 9856 9939 10111 10019 9931 9879 10224 10017 9925

9931 10094 10038 9941 9957 10006 10032 9985 9900 10116

9915 9994 10070 9864 10071 10105 9945 10137 9953 9946

10097 10085 10039 9958 10056 9879 9954 10005 10067 9860

10026 9981 10041 9885 10006 10003 10264 9942 9993 9859

(2)计算素数

计算比n小的指数的个数(用空间换时间的思路)

def count_prime(n):

is_prime = [True] * (n + 1)

i = 2

while i * i <= n:

if (is_prime[i]):

j = i

while (j * i <= n):

is_prime[i * j] = False

j += 1

i += 1

count = 0

for i in range(2, n+1):

if is_prime[i]:

count += 1

print(i, end = " ")

return count

(3)哥德巴赫猜想

任一大于2的偶数,都可表示成两个质数之和。

def goldbach(n):

#find all prime

is_prime = [True] * (n + 1)

i = 2

while i * i <= n:

if is_prime[i]:

j = i

while (j * i <= n):

is_prime[i * j] = False

j += 1

i += 1

#calc amount of prime

count = 0

for i in range(2, n+1):

if is_prime[i]:

count += 1

#two pointer

primes = [None] * count

idx = 0

for i in range(2, n + 1):

if is_prime[i]:

primes[idx] = i

idx += 1

left = 0

right = count - 1

while left < right:

if n == primes[left] + primes[right]:

print(n," = ", primes[left], " + ", primes[right])

left += 1

right -= 1

elif n > primes[left] + primes[right]:

left += 1

else:

right -= 1

2.动态数组

创建空列表

确定此列表是否为空

确定列表中元素个数

给列表中给定位置添加元素

在列表中给定位置删除元素

删除列表中的所有元素

获取列表中给定位置的元素

动态数组的简单实现:

import ctypes

class DynamicArray:

def __init__(self):

'Create an empty array'

self._size = 0

self._capacity = 10

self._eles = self._make_array(self._capacity)

def __len__(self):

return self._size

def is_empty(self):

return self._size == 0

def __getitem__(self, index):

if not 0 <= index

raise ValueError("Invalid index")

return self._eles[index]

def append(self,item):

if self._size == self._capacity:

self._resize(self._capacity * 2)

self._eles[self._size] = item

self._size += 1

def insert(self,index,item):

if self._size == self._capacity:

self._resize(self._capacity * 2)

for k in range(self._size,index,-1):

self._eles[k] = self._eles[k-1]

self._eles[index] = item

self._size += 1

def remove(self,value):

for i in range(self._size):

if self._eles[i] == value:

for j in range(i,self._size-1):

self._eles[j] = self._eles[j+1]

self._eles[self._size-1] = None

self._size -= 1

return

raise ValueError("value not found")

def print(self):

for i in range(self._size):

print(self._eles[i],end=' ')

def _resize(self,capacity):

new_array = self._make_array(capacity)

for k in range(self._size):

new_array[k] = self._eles[k]

self._eles = new_array

self._capacity = capacity

def _make_array(self,capacity):

return (capacity * ctypes.py_object)()

标签:shuffle,python,results,len,range,数组,cards,数据结构,def

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值