邊刷LeetCode邊學習——陣列(一)
陣列相關
基礎知識
Python
在Python中沒有陣列這個說法,類似的有列表(list)
和元組(tuple)
。
列表(list)
列表(list)
是一種可變的有序集合,可以隨時新增和刪除其中的元素。定義一個列表很簡單:
# 列表中的元素型別可以不相同,也可以是一個 list
list = [0,"java",["又是一個list"]]
使用 len(list)
函式可以獲取列表的長度。可以通過索引獲取列表中的元素,索引從0開始;如果索引超出了列表的範圍(0 ≤ i < len(list)
,i 代表索引)會報一個IndexError錯誤,所以,要確保索引不會越界。列表提供了一些方法操作列表中的元素:
# 向列表末尾追加元素 list.append("新增一個") # list -> [0,"java",["又是一個list"],"新增一個"] # 向列表指定位置新增元素 list.insert("Python",2) # list -> [0,"java","Python",["又是一個list"],"新增一個"] # 從list末尾刪除一個元素 list.pop() # list -> [0,"java","Python",["又是一個list"]] # 從列表指定位置刪除一個元素 list.pop(2) # list -> [0,"java",["又是一個list"]] # 改變列表中的某一個元素 list[1] = "Python" # list -> [0,"Python",["又是一個list"]]
元組(tuple)
元組(tuple)
是一種不可變的有序集合,和列表不同的是,元組的元素一旦確定就不可改變。定義一個元組與列表有些許差別:
# 定義一個有元素的
tup = (1,2,"a",[1,2])
# 定義一個空元組
empty_tup = ()
# 只有一個元素,注意如果不帶“,”會當成一個數字
one_tup = (1,)
同樣,元組和列表一樣,也可以通過索引來訪問元素。
注意:元組的不可變指的是指向不變,如果元組的元素本身是一個可變元素,例如列表,那麼會發現這個列表的元素是可以改變的,但是這個列表的指向並沒有變,所以不能說這個元組變化了。比如 上面定義的元組tup的最後一個元素是一個列表,
tup[3][0]=0
這個操作是合法的。
Go
陣列
陣列是一個由固定長度的特定型別元素組成的序列,一個數組可以由零個或多個元素組成。
因為陣列的長度是固定的,因此在Go語言中很少直接使用陣列。和陣列對應的型別是
Slice(切片),它是可以增長和收縮動態序列,slice功能也更靈活陣列的每個元素可以通過索引下標來訪問,索引下標的範圍是從0開始到陣列長度減1的位
置。內建的len函式將返回陣列中元素的個數。預設情況下,陣列的每個元素都被初始化為元素型別對應的零值,對於數字型別來說就是0。
我們也可以使用陣列字面值語法用一組值來初始化陣列
var a [3]int // 長度為3的int陣列,預設每個元素值為0
var b = [3]int{1, 2, 3}
fmt.Printf("\t第一個元素:%d", a[0]) // 獲取第一個元素
fmt.Printf("最後一個元素:%d\r\n", a[len(a)-1]) // 獲取最後一個元素 <==> a[2]
在陣列字面值中,如果在陣列的長度位置出現的是“...”省略號,則表示陣列的長度是根據初始
化值的個數來計算。因此,上面b陣列的定義可以簡化為
var b = [...]int{1, 2, 3}
同時,陣列還可以直接指定下標的值例如 c:=[...]int{1:1,99:-1}
這樣將生成一個長度為100的陣列,下表 1 的值為 1,下標 99 的值為 -1,其他均為0.
切片
Slice(切片)代表變長的序列,序列中每個元素都有相同的型別。一個slice型別一般寫作
[]T,其中T代表slice中元素的型別;slice的語法和陣列很像,只是沒有固定長度而已。一個slice是一個輕量級的資料結構,提供了訪問陣列子序
列(或者全部)元素的功能,而且slice的底層確實引用一個數組物件。一個slice由三個部分
構成:指標、長度和容量。指標指向第一個slice元素對應的底層陣列元素的地址,要注意的
是slice的第一個元素並不一定就是陣列的第一個元素。長度對應slice中元素的數目;長度不
能超過容量,容量一般是從slice的開始位置到底層資料的結尾位置。內建的len和cap函式分
別返回slice的長度和容量。
多個slice之間可以共享底層的資料,並且引用的陣列部分割槽間可能重疊。
演算法題
1、移動零
給定一個數組 nums,編寫一個函式將所有 0 移動到陣列的末尾,同時保持非零元素的相對順序。
示例:
輸入: [0,1,0,3,12]
輸出: [1,3,12,0,0]
說明:
必須在原陣列上操作,不能拷貝額外的陣列。
儘量減少操作次數。
需要用到邏輯判斷和迴圈
Python 邏輯判斷
# 單個條件
if <條件判斷>:
<執行>
# 多個條件 elif 是 else if 的縮寫
if <條件判斷1>:
<執行1>
elif <條件判斷2>:
<執行2>
elif <條件判斷3>:
<執行3>
else:
<執行4>
Python 迴圈
# for ... in 迴圈,常用於遍歷可迭代元素
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
# while 迴圈
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print(sum)
Go 邏輯判斷
// 注意 go 語言的 “{” 與 “}” 不可省略
if condition {
// do something
}
if condition {
// do something
} else {
// do something
}
if condition1 {
// do something
} else if condition2 {
// do something else
} else {
// catch-all or default
}
Go 迴圈
// go 中只有 for 迴圈結構
// 基於計數器的迴圈
for i := 0; i < 5; i++ {
fmt.Printf("This is the %d iteration\n", i)
}
// 基於條件的迴圈
for i >= 0 {
i = i - 1
fmt.Printf("The variable i is now: %d\n", i)
}
示例程式碼:
// Java 程式碼
import java.util.Arrays;
/**
* MoveZero
*/
public class MoveZero {
public static void main(String[] args) {
MoveZero mZero = new MoveZero();
mZero.moveZeroes(new int[]{0,1,0,3,12});
}
public void moveZeroes(int[] nums) {
// soulution1(nums);
soulution2(nums);
System.out.print(Arrays.toString(nums));
}
/**
* 該方法思路是把為 0 的數往後移,遇到了不為0的則交換位置,繼續下一位的移動
*/
public void soulution1(int[] nums){
int len = nums.length;
for (int i = 0; i < len; i++) {
// 如果是0,則往後移,遇到非 0 的就結束移動
if(nums[i]==0){
for (int j = i+1; j < nums.length; j++) {
if(nums[j]!=0){
int temp = nums[j];
nums[j]=nums[i];
nums[i]=temp;
break;
}
}
}
}
}
/**
* 該方法思路是把不為 0 的往遷移,全部移動完之後,剩下的都是0;
* 相比較第一種方法,迴圈次數較少
*/
public void soulution2(int[] nums){
int i = 0;
// 把不是0的往前移動,i就是非0的個數
for (int j = 0; j < nums.length; j++){
if (nums[j] != 0) {
nums[i++] = nums[j];
}
}
// 從i開始剩下的都是 0
for (int k = i; k < nums.length; k++){
nums[k] = 0;
}
}
public void soulution3(int[] nums) {
int s = 0;
int f = 0;
while (f < nums.length) {
if (nums[f] != 0) {
int temp = nums[f];
nums[f] = nums[s];
nums[s] = temp;
s++;
}
f++;
}
}
}
# Python
class MoveZero(object):
def __init__(self):
print("移動零1")
def moveZeroes(self,nums):
# self.solution1(nums)
# self.solution2(nums)
self.solution3(nums)
print(nums)
def solution1(self,nums):
i = 0
for v in nums:
if v == 0:
j = i+1
while j < len(nums):
if nums[j] != 0:
temp = nums[j]
nums[j] = v
nums[i] = temp
break
j+=1
i+=1
def solution2(self,nums):
i = 0
for v in nums:
if v != 0:
nums[i]=v
i+=1
while i < len(nums):
nums[i]=0
i+=1
def solution3(self,nums):
i = 0
j = 0
while i < len(nums):
if nums[i] != 0:
temp = nums[i]
nums[i] = nums[j]
nums[j] = temp
j+=1
i+=1
moveZero = MoveZero()
moveZero.moveZeroes([1,0,3,0,5])
package main
import (
"fmt"
)
func main() {
nusm := [5]int{0, 3, 0, 5, 2}
// 從陣列獲取切片
moveZero(nusm[:])
}
func moveZero(nums []int) {
// solution1(nums)
// solution2(nums)
solution3(nums)
fmt.Print(nums)
}
func solution1(nums []int) {
for i, v := range nums {
if v == 0 {
for j := i + 1; j < len(nums); j++ {
if nums[j] != 0 {
temp := nums[j]
nums[j] = nums[i]
nums[i] = temp
break
}
}
}
}
}
func solution2(nums []int) {
i := 0
for _, v := range nums {
if v != 0 {
nums[i] = v
i++
}
}
for j := i; j < len(nums); j++ {
nums[j] = 0
}
}
func solution3(nums []int) {
s := 0
f := 0
for f < len(nums) {
if nums[f] != 0 {
nums[s], nums[f] = nums[f], nums[s]
s++
}
f++
}
}