算法练习--leetcode 数组

文章目录

爬楼梯问题

输入n阶楼梯,每次爬1或者2个台阶,有多少种方法可以爬到楼顶?

示例1:输入2, 输出2

一次爬2阶;

一次爬1阶;

故两种方法。

示例2:

输入3, 输出3

三个1;

一个1 + 一个 2;

一个2 + 一个1;

思路分析:

采用递归求解

python实现:

python 复制代码
# 递归
def climb_stairs(n):
    if n == 1:
        return 1
    elif n == 2:
        return 2
    elif n >= 3:
        return climb_stairs(n-1) + climb_stairs(n-2)

# 递归优化,避免重复计算(优化效果微小)
def climb_stairs_2(n):
    d = {}
    if n == 1:
        return 1
    elif n == 2:
        return 2
    elif n >= 3:
        if n in d:
            return d.get(n) # 避免一部分递归操作
        cur = climb_stairs(n-1) + climb_stairs(n-2)
        d[n] = cur
        return cur

# 循环一次计算(自底向上依次计算)
# O(n)
def climb_stairs_3(n):
    if n == 1:
        return 1
    elif n == 2:
        return 2
    elif n >= 3:
        a = 1
        b = 2
        result = 0
        for i in range(3, n+1):
            result = a + b
            a = b
            b = result
            
        return result

java实现:

java 复制代码
// O(n)
class Solution{
	public int climbStairs(int n){
		if(n == 1) return 1;
		else if(n == 2) return 2;
		else if(n >= 3){
			int result = 0;
			int a = 1;
			int b = 2;
			for(int i=3; i<=n; i++){
				result = a + b;
				a = b;
				b = result;
			}
			return result;
		}
	}
}

裴波那契数列

类似爬楼梯问题。

两数之和 数组

给定一个整数数组 nums 和一个整数目标值 target,在该数组中找出 和 等于目标值 target 的那两个整数,并返回它们的数组下标。

假设每种输入只会对应一个答案,且数组中同一个【位置】的元素在答案里不能重复出现。

示例 1:

输入:nums = 2,7,11,15, target = 9

输出:0,1

解释:因为 nums0 + nums1 == 9 ,返回 0, 1

示例 2:

输入:nums = 3,2,4, target = 6

输出:1,2

示例 3:

输入:nums = 3,3, target = 6

输出:0,1

暴力解法:

  • 依次遍历元素,计算求和,并比较。
  • 时间复杂度 O ( n 2 ) {O(n^2)} O(n2)
  • python实现
python 复制代码
# O(n^2)
def calcSum(arr, target):
    n = len(arr)
    for i in range(n-1):
        for j in range(i+1, n):
            if arr[i] + arr[j] == target:
                return [i, j]

    raise ValueError("未找到结果")
  • java实现
java 复制代码
在这里插入代码片

哈希优化

  • 遍历数组,索引为 i;
  • 判断 left = target - arrayi ,left 值是否存在于hash;
    • 存在,则返回索引 i 和 hash中left 对应的值;
    • 不存在,则将 arrayi :i 存入hash;
  • 时间复杂度 O ( n ) {O(n)} O(n)
  • python实现
python 复制代码
# python
def optimize_calc_sum(alist, target):
    dict_ = {}
    n = len(alist)
    for i in range(n):
        if target - alist[i] in dict_:
            return [i, dict_.get(target - alist[i])]
        dict_[alist[i]] = i
    raise ValueError("未找到结果")
  • java实现
java 复制代码
在这里插入代码片

合并两个有序数组

给两个非递减排列的整数数组arr1、arr2,m 和 n 分别表示arr1 、arr2的元素个数;合并arr2到arr1中,合并后元素非递减排列。

示例1:

arr1 = 1, 2, 3, 0, 0, 0 m = 3

arr2 = 2, 5, 6 n = 3

合并结果:1,2,***2*** ,3,***5*** ,***6*** 黑体数字为arr2中的元素

示例2:

arr1 = 1

arr2 =

合并结果: 1

python实现:

python 复制代码
arr1 = [1, 3, 4, 0, 0, 0]
m = 3
arr2 = [2, 5, 6]
n = 3

def merge_array(arr1, m, arr2, n):
    # 准备临时数组
    temp = []   # 空间复杂度O(m+n)
    i = 0
    j = 0
    while i < m and j < n:  # O(m+n) 线性复杂度
        if arr1[i] <= arr2[j]:
            temp.append(arr1[i])
            i += 1
        else:
            temp.append(arr2[j])
            j += 1
    if i == m:
        temp.extend(arr2[j:n])
    elif j == n:
        temp.extend(arr1[i:m])

    for i in range(m + n):
        arr1[i] = temp[i]

    print("arr1:", arr1)
    return arr1

java实现:

移动零

给定一个数组array,将内部所有的0移动到数组的末尾,并保持非零元素的相对顺序。必须原位操作,不能拷贝额外的数组。

示例:

输入,0, 1, 0, 3, 12

输出,1, 3, 12, 0, 0

提示:双指针

python实现:

python 复制代码
# 暴力实现
arr = [0, 1, 0, 3, 12, 0, 0, 13, 0, 14, 0, 18, 0, 0, 0]

# 依次将遍历的首个0值与后面的非0置换
def move_zero(arr):
    n = len(arr)
    for i in range(n):
        if arr[i] != 0:
            continue
        k = i # 记录当前0的位置
        j = i + 1 # 下一个元素的位置
        while j < n:
            if arr[j] == 0:
                j += 1
                continue
            arr[k], arr[j] = arr[j], arr[k]
            k = j
            j += 1

    print("result:", arr)
    return arr

# 双指针
# 双指针同时从0开始
# 依次将后一个指针的非0值,放到前一个指针的位置,前一个指针+1,继续下次循环
# 最后将后一个指针处到结束 均赋值0
# 时间复杂度 O(2n)
def move_zero_double_pointer(arr):
    n = len(arr)
    j = 0 # j指针
    for i in range(n): # i指针  两个指针同时从0开始
        if arr[i] != 0:
            arr[j] = arr[i]
            j += 1
    # 将从j开始的元素 全部赋值0
    while j < n:             # 时间复杂度 O(2n)
        arr[j] = 0
        j += 1
    print("result:", arr)
    return arr

java实现:双指针移动0

找到所有数组中消失的数字

给定一个n个整数的数组array,每个元素值在【1,n】之间,找出1-n内没有出现在array中的数字,以数组形式返回。
n为数组的长度;

示例1:

输入:4,3,2,7,8,2,3,1

输出:5,6

示例2:

输入:1,1

输出:2

进阶:可以不借助额外空间且时间复杂度为O(n),解决吗?

python实现:

python 复制代码
# 暴力实现
def find_missing_digit(arr):
    n = len(arr) # [1, ..., n]
    # arr去重
    temp = []  # 空间复杂度O(n)
    for i in range(1, n+1):  # 时间复杂度 O(n)
        if i not in arr:
            temp.append(i)

    print("result:", temp)
    return temp


# 优化空间复杂度O(1)
# 只能依赖数组本身的空间
# 所有元素的值 - 1 可以对应索引,对应索引处的值 都+n 或者2n....
# 而缺失的那些值 - 1 对应的索引处的值肯定没有变化,即 <= n
# 最后循环找到<=n的元素,其索引+1 就是缺失的值
def optimize_find_missing_digit(arr):
    n = len(arr)
    # 空间复杂度为O(1)  只能使用数组本身的空间

    for i in arr:
        idx = (i - 1) % n # 得到对应的索引(拿到的i可能是已改过的) 所以需要还原索引
        arr[idx] += 2 * n

    temp = []  # 存储最终结果的空间不算 额外空间
    for i in range(n):
        if arr[i] <= n:
            temp.append(i + 1)

    print("result:", temp)
    return temp

java实现:

三数之和

给一个整数数组 nums ,判断是否存在三元组 nums\[i, numsj, numsk ] 满足 i != j、i != k 且 j != k ,同时还满足 numsi + numsj + numsk == 0 。返回所有和为 0 且不重复的三元组,如果三个元素只是顺序不同,则算重复的三元组。

示例 1:

输入:-1,0,1,2,-1,-4

输出:\[-1,-1,2,-1,0,1]

解释:

nums0 + nums1 + nums2 = (-1) + 0 + 1 = 0 。

nums1 + nums2 + nums4 = 0 + 1 + (-1) = 0 。

nums0 + nums3 + nums4 = (-1) + 2 + (-1) = 0 。

不同的三元组是 -1,0,1-1,-1,2

注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:0,1,1

输出:\[\]

解释:唯一可能的三元组和不为 0 。

示例 3:

输入:0,0,0

输出:\[0,0,0]

解释:唯一可能的三元组和为 0 。

提示:

3 <= nums.length <= 3000

-105 <= numsi <= 105

python实现:

python 复制代码
# 暴力解法 O(n^3)   会产生重复的三元组
arr = [-1,0,1,2,-1,-4]
def three_nums_sum(arr: List[int]) -> List[List[int]]:
    n = len(arr)
    temp = []
    for i in range(n-2):
        for j in range(i+1, n-1):
            for k in range(j+1, n):
                if arr[i] + arr[j] + arr[k] == 0:
                    temp.append([arr[i], arr[j], arr[k]])

    # result: [[-1, 0, 1], [-1, 2, -1], [0, 1, -1]]
    # 会产生重复的三元组
    print("result:", temp)

    return temp

# 排序 + 双指针
# 时间复杂度 O(n^2)
def optimize_three_nums_sum(nums: List[int]) -> List[List[int]]:
    n = len(nums)
    res = []
    if n < 3:
        return []

    nums.sort() # 排序  快排  O(nlogn)
    res = []
    for i in range(n):  O(n^2)
        if (nums[i] > 0):
            return res
        if (i > 0 and nums[i] == nums[i - 1]):   # 防止重复解
            continue
        # 双指针
        L = i + 1
        R = n - 1
        while (L < R):
            if (nums[i] + nums[L] + nums[R] == 0):
                res.append([nums[i], nums[L], nums[R]])
                # 去除重复
                while (L < R and nums[L] == nums[L + 1]):
                    L = L + 1
                while (L < R and nums[R] == nums[R - 1]):
                    R = R - 1
                L = L + 1
                R = R - 1
            elif (nums[i] + nums[L] + nums[R] > 0):
                R = R - 1
            else:
                L = L + 1
    return res

java实现:

pass

下一篇:算法练习--leetcode 链表

相关推荐
折哥的程序人生 · 物流技术专研1 小时前
Java面试85题图解版 · 特别篇:2026后端高频面试题复盘(算法底层逻辑+高并发架构设计全解析,附Java实战代码)
java·网络·数据库·算法·面试
想吃火锅10052 小时前
【leetcode】14.最长公共前缀js
算法·leetcode·职场和发展
云絮.3 小时前
数据库操作
数据库·mysql·算法·oracle
小林ixn4 小时前
LeetCode 206. 反转链表(迭代 + 递归详解)
算法·leetcode·链表
凡人叶枫4 小时前
Effective C++ 条款17:以独立语句将 newed 对象置入智能指针
java·linux·开发语言·c++·算法
菜鸟‍5 小时前
LeetCode 1 27 和 704 || 两数之和 移除元素 二分查找
算法·leetcode·职场和发展
退休倒计时6 小时前
【每日一题】LeetCode 142. 环形链表 II TypeScript
算法·leetcode·链表·typescript
popcorn_min7 小时前
Digits 手写数字识别:随机森林多分类 + 像素级特征热力图
算法·随机森林·分类
liulilittle7 小时前
拥塞控制:排水终止的两种决策:OR 与 AND
网络·tcp/ip·计算机网络·算法·信息与通信·tcp·通信
weixin_307779138 小时前
从脚本执行到智能体协作:AI辅助测试能力的范式重构
运维·开发语言·人工智能·算法·测试用例