Golang每日一练(leetDay0107) 去除重复字母、最大单词长度乘积

文章提供了两个编程问题的解决方案:一是使用贪心算法和暴力枚举去除字符串中的重复字母,二是通过位运算和哈希表找到没有公共字母的最大长度乘积单词对。示例代码分别用Go语言实现。

 

目录

316. 去除重复字母 Remove Duplicate Letters  🌟🌟

318. 最大单词长度乘积 Maximum-product-of-word-lengths  🌟🌟

🌟 每日一练刷题专栏 🌟

Rust每日一练 专栏

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏


316. 去除重复字母 Remove Duplicate Letters

给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

示例 1:

输入:s = "bcabc"
输出:"abc"

示例 2:

输入:s = "cbacdcbc"
输出:"acdb"

提示:

  • 1 <= s.length <= 10^4
  • s 由小写英文字母组成

代码1:贪心算法

package main

import "fmt"

func removeDuplicateLetters(s string) string {
	stack := []byte{}
	count := [26]int{}
	visited := [26]bool{}
	for i := 0; i < len(s); i++ {
		count[s[i]-'a']++
	}
	for i := 0; i < len(s); i++ {
		count[s[i]-'a']--
		if visited[s[i]-'a'] {
			continue
		}
		for len(stack) > 0 && stack[len(stack)-1] > s[i] && count[stack[len(stack)-1]-'a'] > 0 {
			visited[stack[len(stack)-1]-'a'] = false
			stack = stack[:len(stack)-1]
		}
		stack = append(stack, s[i])
		visited[s[i]-'a'] = true
	}
	return string(stack)
}

func main() {
	s := "bcabc"
	fmt.Println(removeDuplicateLetters(s))

	s = "cbacdcbc"
	fmt.Println(removeDuplicateLetters(s))
}

代码2:暴力枚举

package main

import "fmt"

func removeDuplicateLetters(s string) string {
    lastPos := [26]int{}
    for i := 0; i < len(s); i++ {
        lastPos[s[i]-'a'] = i
    }
    visited := [26]bool{}
    res := []byte{}
    for i := 0; i < len(s); i++ {
        if visited[s[i]-'a'] {
            continue
        }
        for len(res) > 0 && res[len(res)-1] > s[i] && lastPos[res[len(res)-1]-'a'] > i {
            visited[res[len(res)-1]-'a'] = false
            res = res[:len(res)-1]
        }
        res = append(res, s[i])
        visited[s[i]-'a'] = true
    }
    return string(res)
}

func main() {
	s := "bcabc"
	fmt.Println(removeDuplicateLetters(s))

	s = "cbacdcbc"
	fmt.Println(removeDuplicateLetters(s))
}

输出:

abc

acdb


318. 最大单词长度乘积 Maximum-product-of-word-lengths

给你一个字符串数组 words ,找出并返回 length(words[i]) * length(words[j]) 的最大值,并且这两个单词不含有公共字母。如果不存在这样的两个单词,返回 0 。

示例 1:

输入:words = ["abcw","baz","foo","bar","xtfn","abcdef"]
输出:16 
解释这两个单词为 "abcw", "xtfn"。

示例 2:

输入:words = ["a","ab","abc","d","cd","bcd","abcd"]
输出:4 
解释这两个单词为 "ab", "cd"。

示例 3:

输入:words = ["a","aa","aaa","aaaa"]
输出:0 
解释不存在这样的两个单词。

提示:

  • 2 <= words.length <= 1000
  • 1 <= words[i].length <= 1000
  • words[i] 仅包含小写字母

代码1:位运算 + 哈希表

package main

import "fmt"

func maxProduct(words []string) int {
	n := len(words)
	max := func(x, y int) int {
		if x > y {
			return x
		}
		return y
	}
	hash := make(map[int]int, n)
	for _, word := range words {
		mask := 0
		for _, ch := range word {
			mask |= 1 << (uint)(ch-'a')
		}
		hash[mask] = max(hash[mask], len(word))
	}
	res := 0
	for mask1, len1 := range hash {
		for mask2, len2 := range hash {
			if mask1&mask2 == 0 {
				res = max(res, len1*len2)
			}
		}
	}
	return res
}

func main() {
	words := []string{"abcw", "baz", "foo", "bar", "xtfn", "abcdef"}
	fmt.Println(maxProduct(words))

	words = []string{"a", "ab", "abc", "d", "cd", "bcd", "abcd"}
	fmt.Println(maxProduct(words))

	words = []string{"a", "aa", "aaa", "aaaa"}
	fmt.Println(maxProduct(words))
}

代码2:暴力枚举

package main

import "fmt"

func maxProduct(words []string) int {
    n := len(words)
    res := 0
    for i := 0; i < n; i++ {
        for j := i + 1; j < n; j++ {
            if hasNoCommonChar(words[i], words[j]) {
                res = max(res, len(words[i])*len(words[j]))
            }
        }
    }
    return res
}

func hasNoCommonChar(word1, word2 string) bool {
    for i := 0; i < len(word1); i++ {
        for j := 0; j < len(word2); j++ {
            if word1[i] == word2[j] {
                return false
            }
        }
    }
    return true
}

func max(x, y int) int {
    if x > y {
        return x
    }
    return y
}

func main() {
	words := []string{"abcw", "baz", "foo", "bar", "xtfn", "abcdef"}
	fmt.Println(maxProduct(words))

	words = []string{"a", "ab", "abc", "d", "cd", "bcd", "abcd"}
	fmt.Println(maxProduct(words))

	words = []string{"a", "aa", "aaa", "aaaa"}
	fmt.Println(maxProduct(words))
}

输出:

16
4
0


Go1.21 新增 min、max 内置函数,示例如下:

var x, y int
m := min(x)                 // m == x
m := min(x, y)              // m 是 x 和 y 中较小的那个

m := max(x, y, 10)          // m 是 x 和 y 中较大的一个,但至少是10
c := max(1, 2.0, 10)        // c == 10.0(浮点类型)
f := max(0, float32(x))     // f 的类型是 float32

var s []string
_ = min(s...)               // 无效:不允许使用 slice 参数
t := max("", "foo", "bar")  // t == "foo" (string 类型)

升级到V1.21后,不再需要每次用到max, min就要自定义。

对于一些特殊值和清空,例如:浮点参数、负零、NaN和无穷大。min、max 函数结果适用以下规则:
    x        y    min(x, y)    max(x, y)
  -0.0    0.0       -0.0          0.0  
  -Inf      y         -Inf            y    
  +Inf      y           y         +Inf    
   NaN    y        NaN       NaN

第一行:负零比(非负)零小。
第二行:负无穷大比任何其他数字都小。
第三行:正无穷大于任何其他数字。
第四行:如果有任何一个参数是 NaN,结果就是 NaN。


🌟 每日一练刷题专栏 🌟

持续,努力奋斗做强刷题搬运工!

👍 点赞,你的认可是我坚持的动力! 

🌟 收藏,你的青睐是我努力的方向! 

评论,你的意见是我进步的财富!  

 主页:https://hannyang.blog.youkuaiyun.com/ 

Rust每日一练 专栏

(2023.5.16~)更新中...

Golang每日一练 专栏

(2023.3.11~)更新中...

Python每日一练 专栏

(2023.2.18~2023.5.18)暂停更

C/C++每日一练 专栏

(2023.2.18~2023.5.18)暂停更

Java每日一练 专栏

(2023.3.11~2023.5.18)暂停更

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hann Yang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值