LeetCode_easy_中文解析50题_day07

121、 Best Time to Buy and Sell Stock

三十一、题目

给出一个股票的价格序列,买入一次卖出一次,求能获得最大利润。其实就是求一个数组中,后面的数减去前面的数能得到的最大值。最容易想到的肯定是每次选一个数,遍历后面的数,求出直接的差然后和当前最大值进行比较,这样时间复杂度为O(n*n),不推荐。

思路:

找到当前遍历索引(包括当前索引)中的最小值min,然后用当前值减去这个最小值,最后跟我们一开始设置的maxProfit=0 进行比较取大的那一个,那么最终的maxProfit一定大于0,要么等于0。

Example 1:

Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
             Not 7-1 = 6, as selling price needs to be larger than buying price.

Example 2:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
package cn.hnu.leetcode.easy;

public class _121_MaxProfit {
	public int maxProfit(int[] prices) {

		//如果数组是空或者数组的长度小于2,说明数组里面只有一个或者根本没有元素,直接返回0
		//因为不可能当天买当天就卖掉
		if(prices == null||prices.length<2){
			return 0;
		}
		
		//将最大利润设置成0
		int maxProfit = 0;
		
		//整个数组中的最小值姑且就看成数组的第一个元素
		int min = prices[0];
		
		int len = prices.length;
		
		//从数组的第二个元素开始遍历
		for(int i = 1;i<len;i++){
			
			//找到当前遍历的索引之前的最小的元素
			min = Math.min(prices[i] , min);
			
			//用当前的位置的元素减去上面获得的"最小元素",然后跟上一次设置的最大利润比较
			//将最大利润重新设置
			maxProfit = Math.max(prices[i] - min , maxProfit);
		}
		
		//最后返回
		return maxProfit;

	}
}

122、Best Time to Buy and Sell Stock II

三十二、题目

假设有一个数组,其中数组的第i个元素是第i天给定股票的价格。
设计算法以找到最大利润。 假设可以根据需要完成尽可能多的交易(即,多次买入并卖出一股股票)。
注意:您不得同时进行多笔交易(即,必须在再次购买之前卖出股票)

思路:

因为可以连续买入或者卖出,所以只要卖出点比买出点高,就可以卖出获取利润,将利润累加即可。但给出的例子里面有一个【1,2,3,4,5】获取利润是5-1=4,而不是(2-1)+(3-2)+(4-3)+(5-4)= 4.

Example 1:

Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
             Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.

Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.

Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
package cn.hnu.leetcode.easy;

public class _122_MaxProfit {
	public int maxProfit(int[] prices) {
		
		int len = prices.length;
		//如果数组的长度小于等于1,那么也就没有所谓的买入与卖出
		if(len<=1){
			return 0;
		}
		
		int i = 0;
		
		int total = 0;
		
		//使用局部最低点作为买入点,局部最高点为卖出点
		while(i<len){
			int buy,sell;
			
			while(i+1<len&&prices[i+1]<prices[i]){
				i++;
			}
			
			//设置买入点
			buy = i;
			
			//买入与卖出不能是同一天
			i++;
			
			//上面做了i++,那么下面这个循环首先要判断的是是否已经到了数组的最后
			//这里用数组【1 2 3 4】想
			while(i<len&&prices[i]>=prices[i-1]){
				i++;
			}
			
			//设置卖出点
			sell = i-1;
			
			//总利润累加
			total += prices[sell] - prices[buy];
			
		}
		
		return total;
		
	}
}

125、Valid Palindrome

二十三、题目

给定一个字符串,确定它是否是回文,本题只考虑字母数字字符并忽略字母大小写
注意:空字符串定义为有效的回文。

思路:

将字符串中的字符全转换成小写,并将字符串转换成字符数组,然后定义左右指针分别指向头和尾,忽略字符数组中间不是0到1和a到z的字符,比较指针指向的字符是否相等,当left>right循环结束,还没返回false,那么就是一个回文字符串。

Example 1:

Input: "A man, a plan, a canal: Panama"
Output: true

Example 2:

Input: "race a car"
Output: false
package cn.hnu.leetcode.easy;

public class _125_IsPalindrome {
	public boolean isPalindrome(String s) {

		//将给定字符串中的所有字母都改成小写
		char[] chars = s.toLowerCase().toCharArray();
		
		//如果字符串为空或者字符串的长度等于1,则一定是回文字符串
		if(s==null||s.length()==1){
			return true;
		}
		
		//双指针问题,一个指向头,一个指向尾
		int left = 0;
		int right = chars.length-1;
		
		//只要左边的指针位置小于右边,那么一直遍历
		while(left<right){
			
			//看看左边,如果不在a-z或者0-9之间,左指针右移
			if(!((chars[left]>='a'&&chars[left]<='z')||(chars[left]>='0'&&chars[left]<='9'))){
				left++;
			//看看右边,如果不在a-z或者0-9之间,右指针左移
			}else if(!((chars[right]>='a'&&chars[right]<='z')||(chars[right]>='0'&&chars[right]<='9'))){
				right--;
			//如果左指针指向的值等于右指针指向的值,左右指针分别右移和左移
			}else if(chars[left]==chars[right]){
				left++;
				right--;
			//否则的话就返回false
			}else{
				return false;
			}
			
			
		}//end while
		
		//while结束都没返回false,那么就是回文字符串了
		return true;
	}
}

136、Single Number

二十四、题目

给定一个非空的整数数组,除了一个元素外,每个元素都会出现两次。找到这个单一元素
注意:
算法应具有线性运行时间复杂度,能不用额外的内存来实现吗?

思路:

思路一:将数组中的元素以键值对的形式存在map里面,然后数组中每出现相同的数,那么键所对应的值就+1,最终只要返回map集合中值为1的那个key即可

思路二:利用异或操作,n ^ 0 = n   ;   n  ^  n = 0 ;也就是说如果数组中出现同样的数,那么就返回0,如果不存在那就返回这个数;其实就是位运算,而且这个数组指明了除了其中一个数,其它数字都出现两次,实际上就是让用异或运算。而且异或运算满足:

交换律:a ^ b = b ^ a

结合律:a ^ b ^ c  = (a ^ b) ^ c  = a ^ (b ^ c)

其它:a ^ b ^ a = b    ;     a ^ a = 0      ;       a ^ 0 = 0; (就是因为只有一个单数字,其它都是两两相同,那么就可以利用上面的法则转换成这种形式,得到那个最终的result)

Example 1:

Input: [2,2,1]
Output: 1

Example 2:

Input: [4,1,2,1,2]
Output: 4

方法一:

package cn.hnu.leetcode.easy;

import java.util.HashMap;
import java.util.Map;

public class _136_SingleNumber {
	public int singleNumber(int[] nums) {
		
		//创建一个map存储键值对,键表示数组中出现的数字
		HashMap<Integer, Integer> map = new HashMap<>();
		
		//因为数组非空,所以如果是数组长度是1,直接返回第一个元素即可
		if(nums.length==1){
			return nums[0];
		}
		
		int len = nums.length;
		
		//遍历数组放入map集合中
		for(int i = 0;i<len;i++){
			
			Integer count = map.get(nums[i]);
			
			if(count==null){
				count = 0;
			}
			
			map.put(nums[i], count+1);
			
		}
		
		int result = -1;
		
		//最终只要获取map中值为1的元素就完成了本题
		for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
			if(entry.getValue()==1){
				result = entry.getKey();
				break;
			}
		}
		
		return result;

	}
}

方法二:

package cn.hnu.leetcode.easy;
public class _136_SingleNumber {
	
	public static void main(String[] args) {
		
		
		int[] arr = new int[]{4,2,1,2,1};
		System.out.println(singleNumber(arr));
		
	}
	
	public static int singleNumber(int[] nums) {
		
		//如果数组为空或者数组长度小于1,返回-1
		if(nums==null||nums.length<1){
			return -1;
		}
		
		int result = 0;
		
		//利用异或操作,0 ^ n = n ; n ^ n = 0
		for(int i = 0;i<nums.length;i++){
			//System.out.println(result);
			result = result ^ nums[i];
			
		}
		
		return result;
	}
}

141、Linked List Cycle

二十五、题目

给定一个链表,确定它是否有一个循环。

思路:

本题看半天没看懂题目意思,其实就是给定一个链表,也不知道这个链表长啥样,问这个链表是不是有环,可以把链表想象成操场,有两个孩子在围着操场跑,一个速度慢一个速度快,如果操场是飞机场,那是直道,假设无限长,两个小孩跑死也不会相遇,如果是环,那么不管这个换多大,一个速度快,一个速度慢,总有一天会相遇,本题就是利用这种思想,快慢指针完成本题。详见代码。

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

package cn.hnu.leetcode.easy;

import cn.hnu.leetcode.easy.use_Class.ListNode;

public class _140_HasCycle {

	public boolean hasCycle(ListNode head) {
		ListNode fast = head;
		ListNode slow = head;
		
		//前兩個条件好理解,最后一个是因为快指针每次移动两步,我得知道是否为空
		//如果为空,说明就是一个直链,没有环路啦
		while(fast!=null&&slow!=null&&fast.next!=null){
			//快指针每次移动两步(可以是任意,但是不同需要改变while循环条件)
			fast = fast.next.next;
			
			//慢指针每次移动一步
			slow = slow.next;
			
			//如果两个指针相遇,说明有环,返回true
			if(fast == slow){
				return true;
			}
			
		}//end while
		
		//真个while结束无欢就无欢了,返回false
		return false;

	}
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值