Leetcode-数据结构算法刷题

数据结构算法

第一天

1 存在重复元素

给定一个整数数组nums,如果任一值在数组中至少出现两次,返回true,如果数组中的每个元素互不相同,则返回false。

示例1:输入:nums = [1,2,3,1]
	   输出:true
示例2:输入:nums = [1,2,3,4]
	   输出:false
示例3:输入:nums = [1,1,1,3,3,4,3,2,4,2]
	   输出:true

问题求解:这里通常可以有两种思路。
第一种比较好想,先排序,然后再比较相邻的两个元素是否相同,如果相同则true,否则false。
第二种可以利用哈希表,将数组中的整型数字保存到哈希表中,然后通过遍历数组去比对哈希表中该数据是否存在,根据判断依据来返回结果。

代码如下:

class Solution {
	public boolean containDuplicate(int[] nums){
		Arrays.sort(nums);
		for(int i=0; i < nums.length-1; i++){
            if(nums[i] == nums[i+1]){
                return true;
            }
        }
        return false;
	}
}
class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> set = new HashSet<Integer>();
        for (int x : nums) {
            if (!set.add(x)) {
                return true;
            }
        }
        return false;
    }
}
2 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组是数组中的一个连续部分。

示例1:输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
	   输出:6
	   解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例2:输入:nums = [1]
	   输出:1
示例3:输入:nums = [5,4,-1,7,8]
	   输出:23

问题求解:此问题利用了动态规划思想

  • 首先对数组进行遍历,当前最大连续子序列和为sum,结果为ans。
  • 如果sum>0,则说明sum对结果有增益效果,则sum保留并加上当前遍历数字。
  • 如果sum<0,则说明sum对结果无增益效果,需要舍弃,怎sum更新为当前遍历的数字。
  • 每次比较sum和ans的大小,最大值置为ans,遍历结束返回结果。
  • 时间复杂度O(n)

代码如下:

class Solution {
    public int maxSubArray(int[] nums) {
        int ans = nums[0];
        int sum = 0;
        for(int num: nums) {
            if(sum > 0) {
                sum += num;
            } else {
                sum = num;
            }
            ans = Math.max(ans, sum);
        }
        return ans;
    }
}

第二天

3 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

示例1:	输入:nums = [2,7,11,15], target = 9
		输出:[0,1]
		解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例2:输入:nums = [3,2,4], target = 6
	   输出:[1,2]
示例3:输入:nums = [3,3], target = 6
	   输出:[0,1]

问题求解:可以利用哈希表来存储数组中的元素(作为键),值为数组元素的下标。通过判断哈希表中是否包含目标数减去数组中的数字来判断是否满足题目解。

代码如下:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> map = new HashMap<>();
        for(int i=0; i<nums.length; i++){
            if(map.containsKey(target - nums[i])){
                return new int[] {map.get(target-nums[i]) , i};
            }
            map.put(nums[i],i);
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}
4 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例1:输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
	  输出:[1,2,2,3,5,6]
      解释:需要合并 [1,2,3] 和 [2,5,6] 。
      合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例2:输入:nums1 = [1], m = 1, nums2 = [], n = 0
 	  输出:[1]
 	  解释:需要合并 [1] 和 [] 。合并结果是 [1] 。
示例3:输入:nums1 = [0], m = 0, nums2 = [1], n = 1
	  输出:[1]
	  解释:需要合并的数组是 [] 和 [1] 。合并结果是 [1] 。
	  注意,因为 m = 0 ,所以 nums1 中没有元素。
	  nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

问题求解:一、直接把数组nums2放到nums1后边,然后利用sort排序。
二、利用双指针进行比较判断。

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        for(int i=0; i<n; i++){
            nums1[m+i] = nums2[i];
        }
        Arrays.sort(nums1);
    }
}
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i=0,j=0,temp=0;
        while(i<m+n && j<n){
            if(nums1[i] < nums2[j] && nums1[i]!=0){
                i++;
            }
            else if(nums1[i]!=0){
                if(nums1[i]<=nums2[j]){
                    for(int k=m+n-1; k>i; k--){
                    nums1[k] = nums1[k-1];
                    }
                    nums1[i+1] = nums2[j];
                    j++;
                }
                else{
                    temp = nums2[j];
                    nums2[j] = nums1[i];
                    nums1[i] = temp;
                    for(int k=m+n-1; k>i; k--){
                    nums1[k] = nums1[k-1];
                    }
                    nums1[i+1] = nums2[j];
                    j++;
                }
            }
            else{
                nums1[i] = nums2[j++];
            }
        }
        Arrays.sort(nums1);
    }
}

第三天

5 求两个数组的交集

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例1:输入:nums1 = [1,2,2,1], nums2 = [2,2]
		输出:[2,2]
示例2:输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
		输出:[4,9]

问题求解:先将两个数组排序,然后再生成一个新的数组(数组长度为两个数组中最短的那个数组长),然后用两个指针遍历比较两个数组的元素是否相同,如果相同,将元素加入到新的数组中,如果第一个数组的元素比第二个数组的元素小,则第一个数组元素指针向后移动一位,反之同理。

代码如下:

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int length1 = nums1.length, length2 = nums2.length;
        int[] intersection = new int[Math.min(length1,length2)];
        int i = 0, j = 0, k = 0;
        while(i<length1 && j<length2) {
            if(nums1[i] < nums2[j]){
                i++;
            }
            else if(nums1[i]>nums2[j]){
                j++;
            }
            else{
                intersection[k] = nums1[i];
                i++;
                j++;
                k++;
            }
        }
        return Arrays.copyOfRange(intersection, 0, k);
    }
}
6 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例1:输入:[7,1,5,3,6,4]
		输出:5
		解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
		注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例2:输入:prices = [7,6,4,3,1]
		输出:0
		解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

问题求解:一次遍历思路,先定义两个变量来分别保存股票价格的最小值和差额利润的最大值,然后遍历来寻找股票价格数组prices中的最小值和差额的最大值,即可求出结果。

class Solution {
    public int maxProfit(int[] prices) {
        int min = Integer.MAX_VALUE;
        int max = 0;
        for(int i=0; i<prices.length; i++){
            if(prices[i] < min){
                min = prices[i];
            } else if(prices[i] - min > max){
                max = prices[i] - min;
            }
        }
        return max;
    }
}

汉字数字转阿拉伯数字

# 汉字转阿拉伯数字

def chinese_to_num(chinese):

    dict = {'一': 1,
            '二': 2,
            '三': 3,
            '四': 4,
            '五': 5,
            '六': 6,
            '七': 7,
            '八': 8,
            '九': 9,
            '零': 0,
            '十': 10,
            '百': 100,
            '千': 1000,
            '万': 10000,
            }
    i = 0
    result = 0
    while i < (len(chinese)-1):
        str1 = chinese[i]       #总是数字加单位,两两组合
        str2 = chinese[i+1]
        if (str1 in dict) & (str2 in dict) & (str1 != '零'):
            result += (dict.get(str1) * dict.get(str2))
            i += 2
        else:   #遇到零跳过
            i += 1
    if i == len(chinese) - 1:   #不越界的情况下,把个位数字加上
        result += dict.get(chinese[i])
    return result

chinese = "一万零八百零六"
print(chinese_to_num(chinese))

时间复杂度取决于字符串长度为O(n),空间复杂度为定义的字典大小,是固定的,还有一些局部变量,所以为O(1)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值