LeetCode 190周赛

最近一段时间事情好多,好久没有打周赛辽。(我不会承认因为我懒)

趁着思路还热乎,来写一发题解


检查单词是否为句中其他单词的前缀

这个题目用java的字符串来处理还是比较容易的,先用split方法将文章按空格拆开,得到单词数组。

由于题目询问的是文章中的单词是否包含指定字符串的前缀。

因此对于每个单词:

  • 先判断它的长度够不够包含指定字符串。
  • 如果足够长,则取前面一段与指定字符串做比较,相等了就是包含这个指定字符串,返回这个单词的下标+1即可。
  • 最后不要忘记在整个循环结束后加上无答案的结果的-1.
public class Solution1 {
	public int isPrefixOfWord(String sentence, String searchWord) {
		if(sentence.length() == 0)
		{
			return -1;
		}
		String[] words = sentence.split(" ");
		
		for(int i = 0;i < words.length;i++)
		{
			if(words[i].length() >= searchWord.length())
			{
				if(words[i].substring(0,searchWord.length()).equals(searchWord))
				{
					return i + 1;
				}
			}
		}
		return -1;
    }
}

定长子串中元音的最大数目

这个题要求统计字符串中每个定长字串中的元音,并输出其中包含元音的最大数目。

首先,这个题目最朴素的思想是暴力统计每一个字串中元音的数量。但是掐指一算,这个复杂度是O(nm),考虑到数据规模是10^5,这个复杂度有些吃不消,妥妥的TLE。

我们可以对刚刚的算法进行进一步的思考。不难发现起始位置相差为1的两个字串存在大量内容重叠,仅有前后两个字符不一样。
在这里插入图片描述

因此我们可以通过一个滑动窗口来解决这个问题。这个窗口每向前走一步,就统计新加入的单词是否为元音,并抛弃最末尾的单词,抛弃的时候记得修正序列中元音的个数。

public class Solution2 {
	//判断元音的方法
	private boolean isVowel(char ch)
	{
		switch(ch)
		{
		case 'a':return true;
		case 'e':return true;
		case 'i':return true;
		case 'o':return true;
		case 'u':return true;
		default :return false;
		}
	}
	public int maxVowels(String s, int k) {
		char[] string = s.toCharArray();
		int cnt = 0;
		int ans = 0;
		//预处理窗口
		for(int i = 0;i < k - 1;i++)
		{
			if(isVowel(string[i]))
			{
				cnt++;
			}
		}
		for(int i = k - 1;i < string.length;i++)
		{
			if(isVowel(string[i]))//加入新元素
			{
				cnt++;
			}
			ans = Math.max(ans, cnt);//答案
			if(isVowel(string[i - k]))//删除末尾元素
			{
				cnt--;
			}
		}
		return ans;
    }
}

二叉树中的伪回文路径

这是个考察递归遍历二叉树以及回文串性质的题目。对于这个题目,有两点是值得注意的:

  1. 利用递归遍历从根到叶子的路径,并统计期间路过节点的值出现的次数,在叶子节点统计答案。
  2. 一些字符可以排列成一个回文串,当且仅当其中出现次数为奇数的字符数量不超过一个。

对于第一点,统计次数,由于题目中将节点的值限制在1-9,因此可以直接采用数组进行统计。
如果没有这个限制,可能就需要使用到map或者其他的数据结构来处理这个问题。

class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
     TreeNode() {}
     TreeNode(int val) { this.val = val; }
     TreeNode(int val, TreeNode left, TreeNode right) {
         this.val = val;
         this.left = left;
         this.right = right;
     }
 }
public class Solution3 {
	
	static int ans = 0;	//答案
	
	private boolean charge(int[] cnt)	//判断是否可以形成回文序列
	{
		boolean flag = false;
		for(int i = 1;i <= 9;i++)
		{
			if(cnt[i] % 2 == 1)
			{
				if(flag)
				{
					return false;
				}
				flag = true;
			}
		}
		return true;
	}
	
	private void dfs(TreeNode root,int[] cnt)
	{
		cnt[root.val] ++;	//统计该节点的值
		
		if(root.left == null && root.right == null)//叶子节点,统计答案
		{
			if(charge(cnt))
			{
				ans++;
			}
		}
		
		if(root.left != null)
		{
			dfs(root.left,cnt);
		}
		if(root.right != null)
		{
			dfs(root.right,cnt);
		}
		cnt[root.val] --;//回溯时一定要删去该层的统计
	}
	
	public int pseudoPalindromicPaths (TreeNode root) {
		int[] cnt = new int[10];
		dfs(root,cnt);
        return ans;
    }
}

两个子序列的最大点积

”一般来说,最后一题,都是个dp——沃茨基硕德”

这个题目也不例外 (好像大多数子序列的题都是dp)

思路嘛。。。可能会有些绕,但是不难理解,但请原谅我的语文不好,有口难辩QAQ。就先把通过的代码放在这里吧。(我尽量在注释中阐明我的想法。)

public class Solution4 {
	public int maxDotProduct(int[] nums1, int[] nums2) {
		int[] dp = new int[nums2.length];
		
		
		for(int i = 0;i < nums2.length;i++)//初始化dp数组
		{
			dp[i] = 1 << 31;
		}
		
		for(int i = 0,max;i < nums1.length;i++)//遍历数组1
		{
			max = 1 << 31;			//挑选前项的最大值
			for(int j = 0,temp;j < nums2.length;j++)//遍历数组2
			{
				//dp[j]表示对于nums1的前i位以及nums2数组前j位元素中最大的点积值
				//如果取nums1中第i位元素与nums2中第j位元素的点积,则该位值为前j-1项最大值(小于零取零)加上nums1[i]*nums2[j]。否则该位不变
				temp = dp[j];
				dp[j] = Math.max(temp,nums1[i] * nums2[j] + Math.max(0, max));	
				max = max > temp ? max : temp;	//统计前j-1为最大值
			}
		}
		int ans = 1 << 31;
		for(int num : dp)//统计答案
		{
			ans = ans > num ? ans : num;
		}
		return ans;
    }
}

猜你喜欢

转载自blog.csdn.net/wayne_lee_lwc/article/details/106312460