如何从 int Kotlin 数组中获得最长的连胜
How to get longest streak from an array of int Kotlin
我正在写一个故事,想知道如何解决这个类似于我当前工作的问题,因此每周连续运动被定义为一个或多个连续的活跃周,用户在其中进行了锻炼。所以假设给定了一组活跃用户天数,我们需要找出最长的每周活跃用户天数的长度。
这里数组中的每个元素代表日历中任意星期一的偏移量(例如,2022 年 2 月 4 日,星期四)。
偏移量是零索引的。
一些有用的提示是:
- 活动日 在一个日历日内用户至少进行一次锻炼
- 活跃周是一个日历周,从星期一开始,用户至少有一个活跃日
- 每周连续是用户锻炼历史中活跃的一周或多周(连续)
连胜的长度定义为连胜中的活跃周数
这是我的代码:
val str1 = arrayOf(9, 14, 365, 366, 367) //2
val str2 = arrayOf(2, 22, 29, 37, 43, 366, 391) //4
fun findLongestStreak(callDays: Array<Int>): Int{
}
卡了一个星期的这个函数最简单的写法是什么?
你可以这样做
val str1 = arrayOf(9, 14, 365, 366, 367) //2
val str2 = arrayOf(2, 22, 29, 37, 43, 366, 391) //4
fun toWeek(day: Int) = day / 7
fun activeWeeks(days: Array<Int>) = days.map(::toWeek).toSet().sorted()
// find runs of consecutive numbers in a list of integers,
// and return a list of those runs' lengths
fun getStreaks(nums: List<Int>): List<Int> =
if (nums.isEmpty()) emptyList()
// We're going to iterate over each adjacent pair of numbers, so we can check
// if the second number immediately follows the first, so we can add to
// the current streak.
// Since we're looking at the second number in each pair, the first in the list
// (we know there's at least one) is a special case - so we start the list
// we're building up with a streak of 1, representing that first number
else nums.zipWithNext().fold(mutableListOf(1)) { streaks, (prev, current) ->
streaks.apply {
// if the second number (the one we're checking) follows the first,
// add 1 to the most recent streak length in the list
if (current == prev + 1) streaks[lastIndex] += 1
// if they're not consecutive, we need to start a new streak for this number
else streaks.add(1)
}
}
fun findLongestStreak(callDays: Array<Int>): Int =
callDays.run(::activeWeeks)
.run(::getStreaks)
.run { maxOrNull() ?: 0 }
这主要是解释 - 基本上我使用 toSet()
将所有 天数 转换为相应的 周数 删除重复项并 sorted
将其转换为 List
升序 周数
然后 fold
函数从第一个 周数 的连续 1 开始,然后完成其余部分其中,将每个与前 周数 进行比较。如果是连续的,将 1 添加到当前连胜。如果不是,则开始一个长度为 1 的新连胜。 (如果你不喜欢 fold
,你可以用相同的逻辑做一个 for
循环)
这样你就得到了一个连胜长度列表,你可以选择最长的那个
您可以使用具有锻炼周唯一值的 Set
。然后用 non-consecutive 周过滤集合(想法是对于任意一天,它不应该属于刚好等于前一天的周 + 1 的周);
最终,结果的大小就是您所需要的(活跃的离散周):
更新:
使用 toSet()
简化而不是 for 循环更线性:
fun findLongestStreak(callDays: Array<Int>) = callDays.map { it / 7 }.toSet()
.let { it.filter { day -> !it.contains(day - 1) } }.size
原回答:
fun findLongestStreak(callDays: Array<Int>): Int {
val workoutWeeks = mutableSetOf<Int>() // all the workout weeks
for (day in callDays) workoutWeeks.add(day / 7)
return workoutWeeks.filter { !workoutWeeks.contains(it - 1) }.size
}
请注意,day / 7
returns 周数偏移同样指的是它们相对于基准星期一的偏移。
该代码基于以下想法:连续周减去它们在数组中的位置索引会导致相同(无意义)的数字,而对于两个 non-consecutive 周,这两个数字将不同:
val str1 = arrayOf(9, 14, 365, 366, 367)
val str2 = arrayOf(2, 22, 29, 37, 43, 366, 391)
fun findLongestStreak(callDays: Array<Int>): Int {
return callDays
.map { it / 7 } // [1, 2, 52, 52, 52]
.toSet() // [1, 2, 52]
.mapIndexed { index, i -> i - index } // [1, 1, 50]
.groupBy { it } // {1=[1, 1], 50=[50]}
.maxOf { it.value.count() } // 2
}
println(findLongestStreak(str1)) // 2
println(findLongestStreak(str2)) // 4
我正在写一个故事,想知道如何解决这个类似于我当前工作的问题,因此每周连续运动被定义为一个或多个连续的活跃周,用户在其中进行了锻炼。所以假设给定了一组活跃用户天数,我们需要找出最长的每周活跃用户天数的长度。 这里数组中的每个元素代表日历中任意星期一的偏移量(例如,2022 年 2 月 4 日,星期四)。
偏移量是零索引的。 一些有用的提示是:
- 活动日 在一个日历日内用户至少进行一次锻炼
- 活跃周是一个日历周,从星期一开始,用户至少有一个活跃日
- 每周连续是用户锻炼历史中活跃的一周或多周(连续) 连胜的长度定义为连胜中的活跃周数
这是我的代码:
val str1 = arrayOf(9, 14, 365, 366, 367) //2
val str2 = arrayOf(2, 22, 29, 37, 43, 366, 391) //4
fun findLongestStreak(callDays: Array<Int>): Int{
}
卡了一个星期的这个函数最简单的写法是什么?
你可以这样做
val str1 = arrayOf(9, 14, 365, 366, 367) //2
val str2 = arrayOf(2, 22, 29, 37, 43, 366, 391) //4
fun toWeek(day: Int) = day / 7
fun activeWeeks(days: Array<Int>) = days.map(::toWeek).toSet().sorted()
// find runs of consecutive numbers in a list of integers,
// and return a list of those runs' lengths
fun getStreaks(nums: List<Int>): List<Int> =
if (nums.isEmpty()) emptyList()
// We're going to iterate over each adjacent pair of numbers, so we can check
// if the second number immediately follows the first, so we can add to
// the current streak.
// Since we're looking at the second number in each pair, the first in the list
// (we know there's at least one) is a special case - so we start the list
// we're building up with a streak of 1, representing that first number
else nums.zipWithNext().fold(mutableListOf(1)) { streaks, (prev, current) ->
streaks.apply {
// if the second number (the one we're checking) follows the first,
// add 1 to the most recent streak length in the list
if (current == prev + 1) streaks[lastIndex] += 1
// if they're not consecutive, we need to start a new streak for this number
else streaks.add(1)
}
}
fun findLongestStreak(callDays: Array<Int>): Int =
callDays.run(::activeWeeks)
.run(::getStreaks)
.run { maxOrNull() ?: 0 }
这主要是解释 - 基本上我使用 toSet()
将所有 天数 转换为相应的 周数 删除重复项并 sorted
将其转换为 List
升序 周数
然后 fold
函数从第一个 周数 的连续 1 开始,然后完成其余部分其中,将每个与前 周数 进行比较。如果是连续的,将 1 添加到当前连胜。如果不是,则开始一个长度为 1 的新连胜。 (如果你不喜欢 fold
,你可以用相同的逻辑做一个 for
循环)
这样你就得到了一个连胜长度列表,你可以选择最长的那个
您可以使用具有锻炼周唯一值的 Set
。然后用 non-consecutive 周过滤集合(想法是对于任意一天,它不应该属于刚好等于前一天的周 + 1 的周);
最终,结果的大小就是您所需要的(活跃的离散周):
更新:
使用 toSet()
简化而不是 for 循环更线性:
fun findLongestStreak(callDays: Array<Int>) = callDays.map { it / 7 }.toSet()
.let { it.filter { day -> !it.contains(day - 1) } }.size
原回答:
fun findLongestStreak(callDays: Array<Int>): Int {
val workoutWeeks = mutableSetOf<Int>() // all the workout weeks
for (day in callDays) workoutWeeks.add(day / 7)
return workoutWeeks.filter { !workoutWeeks.contains(it - 1) }.size
}
请注意,day / 7
returns 周数偏移同样指的是它们相对于基准星期一的偏移。
该代码基于以下想法:连续周减去它们在数组中的位置索引会导致相同(无意义)的数字,而对于两个 non-consecutive 周,这两个数字将不同:
val str1 = arrayOf(9, 14, 365, 366, 367)
val str2 = arrayOf(2, 22, 29, 37, 43, 366, 391)
fun findLongestStreak(callDays: Array<Int>): Int {
return callDays
.map { it / 7 } // [1, 2, 52, 52, 52]
.toSet() // [1, 2, 52]
.mapIndexed { index, i -> i - index } // [1, 1, 50]
.groupBy { it } // {1=[1, 1], 50=[50]}
.maxOf { it.value.count() } // 2
}
println(findLongestStreak(str1)) // 2
println(findLongestStreak(str2)) // 4