2-Remove Duplicates from Sorted Array
题目大意
给定一个有序数组 nums,对数组中的元素进行去重,使得原数组中的每个元素只有一个。最后返回去重以后数组的长度值。
代码
fun main() {
var nums = intArrayOf(1,1,2,3,4)
println(removeDuplicates(nums))
}
fun removeDuplicates(nums: IntArray): Int {
if (nums.isEmpty()) return 0
var pointer = 0
var uniqueNums = 1
for (itemOne in nums) {
if(nums[pointer]!=itemOne){
pointer++
nums[pointer]=itemOne
uniqueNums++
}
}
return uniqueNums
}
4
3-Remove Element
题目大意
给定一个数组 nums 和一个数值 val,将数组中所有等于 val 的元素删除,并返回剩余的元素个数
代码
fun main() {
var nums = intArrayOf(3, 2, 2, 3)
var target = 3
println(removeElement(nums, target ))
}
fun removeElement(nums: IntArray, target: Int): Int {
if (nums.isEmpty()) return 0
var result = 0
for (item in nums) {
if (item != target) {
result++
}
}
return result
}
2
4-Search Insert Position
题目大意
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
解题思路
给出一个已经从小到大排序后的数组,要求在数组中找到插入 target 元素的位置。
这一题是经典的二分搜索的变种题,在有序数组中找到最后一个比 target 小的元素。
代码
fun main() {
var nums = intArrayOf(1, 3, 5, 6)
var target = 5
println(searchInsert(nums, target))
}
fun searchInsert(nums: IntArray, target: Int): Int {
if (nums.isEmpty()) return 0
var low = 0
var high = nums.size - 1
while (low <= high) {
var mid = (low + high) / 2
when {
nums[mid] == target -> return mid
nums[mid] > target -> high = mid - 1
else -> low = mid + 1
}
}
return low
}
2
5-Plus One
题目大意
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
解题思路
给出一个数组,代表一个十进制数,数组的 0 下标是十进制数的高位。要求计算这个十进制数加一以后的结果。
简单的模拟题。从数组尾部开始往前扫,逐位进位即可。最高位如果还有进位需要在数组里面第 0 位再插入一个 1 。
代码
fun main() {
var nums = intArrayOf(9, 9, 9)
println(plusOne(nums).mapIndexed { index, value -> value })
}
fun plusOne(digits: IntArray): IntArray {
if (digits.isEmpty()) return intArrayOf()
for (i in digits.size - 1 downTo 0) {
if (digits[i] != 9) {
digits[i]++
break
} else {
digits[i] = 0
}
if (digits[0] == 0) {
var res = IntArray(digits.size + 1)
res[0] = 1
return res
}
}
return digits
}
[1, 0, 0, 0]
5-Merge Sorted Array
题目大意
合并两个已经有序的数组,结果放在第一个数组中,第一个数组假设空间足够大。要求算法时间复杂度足够低。
解题思路
为了不大量移动元素,就要从2个数组长度之和的最后一个位置开始,依次选取两个数组中大的数,从第一个数组的尾巴开始往头放,只要循环一次以后,就生成了合并以后的数组了。
代码
fun main() {
var nums1 = intArrayOf(1,2,3,0,0,0)
var nums2 = intArrayOf(2,5,6)
var m = 3
var n=3
merge(nums1,m,nums2,n)
println(nums1.mapIndexed { index, value -> value })
}
fun merge(nums1: IntArray, m: Int, nums2: IntArray, n: Int): Unit {
var tail1 = m - 1
var tail2 = n - 1
var finished = m + n - 1
while (tail1 >= 0 && tail2 >= 0) {
nums1[finished--] = if (nums1[tail1] > nums2[tail2]) {
nums1[tail1--]
} else {
nums2[tail2--]
}
}
while (tail2>=0){
nums1[finished--]=nums2[tail2--]
}
}
[1, 2, 2, 3, 5, 6]
6-Pascal’s Triangle
Input: 5
Output:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
题目大意
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。在杨辉三角中,每个数是它左上方和右上方的数的和。
解题思路
- 给定一个 n,要求打印杨辉三角的前 n 行。
- 简单题。按照杨辉三角的生成规则循环打印即可。
代码
fun main() {
println(generate(3))
}
fun generate(numRows: Int): List<List<Int>> {
var result = ArrayList<List<Int>>()
for (i in 0 until numRows){
var list=ArrayList<Int>()
for (j in 0 until i+1){
if (j==0 ||j==i){
list.add(1)
}else{
var a=result[i-1][j-1]
var b=result[i-1][j]
list.add(a+b)
}
}
result.add(list)
}
return result
}
[[1], [1, 1], [1, 2, 1]]
6-Pascal’s Triangle 2
题目大意
给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。
解题思路
代码
fun main() {
println(getRow(4))
}
fun getRow(rowIndex: Int): List<Int> {
var ans = MutableList<Int>(rowIndex + 1) { 1 }
var temp: Long = 1
for (i in 1..rowIndex) {
temp = temp * (rowIndex - i + 1) / i
ans[i] = temp.toInt()
}
return ans
}
[1, 4, 6, 4, 1]
7- Best Time to Buy and Sell Stock
题目大意
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。注意你不能在买入股票前卖出股票。
解题思路
题目要求找出股票中能赚的钱最多的差价
这一题也有多个解法,可以用 DP,也可以用单调栈
var nums1 = intArrayOf(7,1,5,3,6,4)
println(maxProfit(num1))
// 解法一 模拟 DP
fun maxProfit(prices: IntArray): Int {
if (prices.isEmpty()) return 0
var min =prices[0]
var maxProfit=0
prices.forEach { item->
if (item-min >maxProfit){
maxProfit =item - min
}
if (item<min){
min=item
}
}
return maxProfit
}
5
8- Single Number
题目大意
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。要求算法时间复杂度是线性的,并且不使用额外的辅助空间。
解题思路
题目要求不能使用辅助空间,并且时间复杂度只能是线性的。
题目为什么要强调有一个数字出现一次,其他的出现两次?我们想到了异或运算的性质:任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了。于是最终做法是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其他数字都出现了两次,在异或中全部抵消掉了。利用的性质是 x^x = 0。
println(0 xor 2) 2
println(2 xor 2) 2
println(0 xor 1) 1
代码
fun main() {
var nums3 = intArrayOf(2, 2, 1)
println(singleNumber(nums3))
}
fun singleNumber(nums: IntArray): Int {
var ans = 0
val len: Int = nums.size
for (i in 0 until len) {
ans = ans xor nums[i]
}
return ans
}
1
9- Majority Element
摩尔投票算法
题目大意
给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在众数。
解题思路
题目要求找出数组中出现次数大于 ⌊ n/2 ⌋ 次的数。要求空间复杂度为 O(1)。简单题。
这一题利用的算法是 Boyer-Moore Majority Vote Algorithm。 https://www.zhihu.com/question/49973163/answer/235921864
代码
var nums3 = intArrayOf(3,2,3)
println(majorityElement(nums3))
// 解法一 时间复杂度 O(n) 空间复杂度 O(1) 摩尔投票算法
fun majorityElement(nums: IntArray): Int {
var res = nums[0]
var count=0
nums.forEach {
if (count==0){
res =it
count=1
}else{
if (it ==res){
count++
}else{
count--
}
}
}
return res
}
3
10- Contains Duplicate
题目大意
这是一道简单题,如果数组里面有重复数字就输出 true,否则输出 flase。
解题思路
用 map 判断即可。
代码
var nums3 = intArrayOf(1,2,3,1)
println(containsDuplicate(nums3))
fun containsDuplicate(nums: IntArray): Boolean {
var record = HashSet<Int>()
nums.forEach {
if (record.contains(it)) {
return true
}
println("1111111111")
record.add(it)
}
return false
}
true