数组相关
基础知识
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++
}
}