leetcode-hot100刷题第一天

一、两数之和问题(leetcode-1)

问题描述

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

示例

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解法分析

(1):暴力法实现:很容易想到的一种解法,对数组中每个元素x进行遍历,并查找是否存在一个值与 target - x相等的目标元素。时间复杂度为O(n^2),相对较高,空间复杂度为O(1)。
(2):两遍哈希法:为了对运行时间复杂度进行优化,我们需要一种更有效的方法来检查数组中是否存在目标元素。如果存在,我们需要找出它的索引。保持数组中的每个元素与其索引相互对应的最好方法是什么?哈希表。第一次遍历时将数组的nums[i]作为key,i作为value存入哈希表中,第二次遍历哈希表中每个元素时,可以直接用哈希表查找,将时间复杂度降低为了O(n),但是相应的我们用了时间换空间的方法,因此其空间复杂度变为了O(n);
(3):一遍哈希法:这其实是对两遍哈希法的一种优化,我们在每次向哈希表中存储元素时,可以直接查找当前哈希表中是否有满足条件的元素,有就直接返回结果,没有再将当前元素存入哈希表。

代码实现

    //本题有暴力法、两遍哈希、一遍哈希等多种解法,本次采用一遍哈希
	public static int[] twoSum(int[] nums, int target) {
		Map<Integer, Integer> map = new HashMap<Integer, Integer>(); //创建哈希表
		for(int i = 0 ; i < nums.length ; i++) { //遍历数组元素
			int temp = target - nums[i]; 
			if(map.containsKey(temp)) { //如果当前map中存放有目标值与当前数组元素得差值,直接返回结果
				return new int [] {map.get(temp),i};
			}
			map.put(nums[i], i); //没有则把当前nums[i]作为key,i作为value存入map
		}
		throw new IllegalArgumentException("No two sum solution!"); //没找到则抛出自定义异常
    }

二、两数相加问题(leetcode-2)

问题描述

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

解法分析

此题解法较为简单,类似于初等数学运算,因为链表各自的位数是按照逆序的方式存储,所以可以直接从l1和l2的表头开始相加,并设置一个进位carry用于保存进位即可。
(注意区别’/‘是取商,’%'是取余数)

代码实现

	public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
		 ListNode dummyHead = new ListNode(0); //创建结果链表的头节点
		 ListNode p = l1, q = l2, curr = dummyHead; 
		 int carry = 0; //声明carry变量用于保存进位值
		 while (p != null || q != null) { 
			 //若有链表已经遍历到头,便将其值置为0
			 int x = (p != null) ? p.val : 0;
		     int y = (q != null) ? q.val : 0;
		     int sum = carry + x + y; 
		     carry = sum / 10; //计算进位值
		     curr.next = new ListNode(sum % 10); //计算当前节点的值
		     curr = curr.next; //将指针指向下一节点
		     if (p != null) p = p.next; 
		     if (q != null) q = q.next;
		  }
		  if (carry > 0) {
		     curr.next = new ListNode(carry); //遍历完成后若任有进位值,则加一个节点
		  }
		  return dummyHead.next;
    }

三、无重复字符的最长字串(leetcode-3)

问题描述

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例

(1) 输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
(2) 输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
(3) 输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。

解法分析

(1)、暴力法:逐个检查所有的子字符串,看它是否不含有重复的字符。对每个字串调用编写的allUnique()函数,该函数内部可以使用hashset来判断重复字符。
(2)、滑动窗口:也是利用hashSet的一种方法,对字符串的每个下标为i的字符,令j=i+1;然后向右滑动到遇到重复元素为止。
(3)、优化滑动窗口:上面的滑动窗口法需要执行2n步骤,但其实如果 s[j] 在 [i,j) 范围内有与 j’重复的字符,我们不需要逐渐增加i。我们可以直接跳过 [i,j’]范围内的所有元素,并将 i 变为 j’ + 1。

代码实现

暴力法

	public static int lengthOfLongestSubstring(String s) {
		int n = s.length();
		int ans = 1;
		for(int i = 0 ; i < n-1 ; i++) {
			for(int j = i+1 ; j < n ; j++) {
				if(allUnique(s, i, j)) { //遍历得到所有字串并进行判断是否有重复元素
					ans = Math.max(ans, j-i+1); //更新最大无重复字串长度
				}
			}
		}
		return ans;
	}

	public static boolean allUnique(String s, int start, int end) {
		Set<Character> set = new HashSet<Character>();
		for(int i = start ; i < end ; i++) {
			Character character  = s.charAt(i);
			if(set.contains(character)) { //如果set中已经包含当前元素,说明已重复,返回false
				return false;
			}
			set.add(character); //不包含则把当前元素加入进set中
		}
		return true;
	}

滑动窗口

	public static int lengthOfLongestSubstring(String s) {
		int n = s.length();
		Set<Character> set = new HashSet<Character>(); //创建set用于保存滑动窗口中的值
		int ans = 0 , i = 0 , j = 0; 
		while(i < n && j < n) { 
			if(! set.contains(s.charAt(j))) { //如果当前set不包含当前j位置字符,j向右滑动
				set.add(s.charAt(j++));
				ans = Math.max(ans, j-i);
			}else {
				set.remove(s.charAt(i++)); //包含了说明以i开头的最长字符串已经找到,i向右滑动。
			}
		}
		return ans;
	}

优化滑动窗口

	public static int lengthOfLongestSubstring(String s) {
		int n = s.length(), ans = 0;
        Map<Character, Integer> map = new HashMap<>(); // 存储字符下标
        for (int j = 0, i = 0; j < n; j++) {
            if (map.containsKey(s.charAt(j))) {
                i = Math.max(map.get(s.charAt(j)), i);
            }
            ans = Math.max(ans, j - i + 1);
            map.put(s.charAt(j), j + 1);
        }
        return ans;
	}

四、寻找两个有序数组的中位数(leetcode-4)

问题描述

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。

示例

示例1:
nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0

示例2:
nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

解法分析

此题如果不考虑时间复杂度较为轻松,只用将两个数组归并排序后求解即可,但时间复杂度为O(m+n)不满足要求,leetcode给出的官方题解分析较多,考虑到篇幅原因,这篇博客先贴出代码,后面将专门写一篇博客进行详细分析。

代码实现

	public static double findMedianSortedArrays(int[] A, int[] B) {
        int m = A.length;
        int n = B.length;
        if (m > n) { // to ensure m<=n
            int[] temp = A; A = B; B = temp;
            int tmp = m; m = n; n = tmp;
        }
        int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
        while (iMin <= iMax) {
            int i = (iMin + iMax) / 2;
            int j = halfLen - i;
            if (i < iMax && B[j-1] > A[i]){
                iMin = i + 1; // i is too small
            }
            else if (i > iMin && A[i-1] > B[j]) {
                iMax = i - 1; // i is too big
            }
            else { // i is perfect
                int maxLeft = 0;
                if (i == 0) { maxLeft = B[j-1]; }
                else if (j == 0) { maxLeft = A[i-1]; }
                else { maxLeft = Math.max(A[i-1], B[j-1]); }
                if ( (m + n) % 2 == 1 ) { return maxLeft; }

                int minRight = 0;
                if (i == m) { minRight = B[j]; }
                else if (j == n) { minRight = A[i]; }
                else { minRight = Math.min(B[j], A[i]); }

                return (maxLeft + minRight) / 2.0;
            }
        }
        return 0.0;
    }

五、最长回文字符串(leetcode-5)

问题描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例

示例1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。

示例2:
输入: “cbbd”
输出: “bb”

解法分析

本题解法较多,这里采用动态规划法求解:使用dp[i][j]数组;dp[i][j]表示字符串中从i到j的位置是否为回文;先初始化1字母和2字母回文,然后用状态转移方程:dp[i+1][j+1] = dp[i][j] if(i和j处字符相同)。

代码实现

    public static String longestPalindrome(String s) {
		if(s == null || s.equals("")) {
            return s;
        }

        int len = s.length();
        char[] chars = s.toCharArray();

        //状态定义
        boolean[][] dp = new boolean[len][len];
        
        // 1字母初始化
        for(int i = 0; i < len; i++) {
            dp[i][i] = true;
        }

        // 2字母初始化 P(i,i+1)=(Si==Si+1)
        for(int i = 0; i < len - 1; i++) {
            dp[i][i+1] = (chars[i] == chars[i+1]);
        }

        int left = 0;
        int right = 0;
        int max = 1;
        for(int i = len - 2; i >= 0; i--) {
            for(int j = i + 1; j < len; j++) {
                // P(i,j)=(P(i+1,j−1) and Si==Sj)
                if(j != i+1) {
                    dp[i][j] = dp[i+1][j-1] && chars[i] == chars[j];
                }
                if(dp[i][j] && max < j - i + 1) {
                    max = j - i + 1;
                    left = i;
                    right = j;
                }
            }
        }
        return s.substring(left, right+1);
	}

总结

这是博主写的第一篇博客,博客问题和解法都主要来源于leetcode官网,算法的学习还是在于平时多写多积累,亡羊补牢,希望现在为时未晚吧。以后还会考虑开一些其他的栏目,目前还打算做一下面试知识的总结栏目,希望不会鸽吧~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值