860,柠檬水找零
/**
* 在柠檬水摊上,每一杯柠檬水的售价为 5 美元。
*
* 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。
*
* 每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。
* 你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。
*
* 注意,一开始你手头没有任何零钱。
*
* 如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
*
* 示例 1:
*
* 输入:[5,5,5,10,20]
* 输出:true
* 解释:
* 前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
* 第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
* 第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
* 由于所有客户都得到了正确的找零,所以我们输出 true。
* 示例 2:
*
* 输入:[5,5,10]
* 输出:true
* 示例 3:
*
* 输入:[10,10]
* 输出:false
* 示例 4:
*
* 输入:[5,5,10,10,20]
* 输出:false
* 解释:
* 前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。
* 对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。
* 对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。
* 由于不是每位顾客都得到了正确的找零,所以答案是 false。
*
*
* 提示:
*
* 0 <= bills.length <= 10000
* bills[i] 不是 5 就是 10 或是 20
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/lemonade-change
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
* @param args
*/
public static void main( String[] args )
{
int[] bills={5,5,5,10,20};
System.out.println(lemonadeChange( bills ));
int[] bills2={5,5,5,5,20,20,5,5,5,5};
System.out.println(lemonadeChange( bills2 ));
}
public static boolean lemonadeChange(int[] bills) {
int[] money=new int[3]; //保存 5,10,20 钱数量。
//注意是排队购买
for( int i = 0; i < bills.length; i++ )
{
if(bills[i]==5){
money[0]++;
}else if(bills[i]==10){
money[1]++;
//判断是否5元够支付
if(money[0]>0){
money[0]--;
}else {
return false;
}
}else {
if(money[1]>0&&money[0]>0){//先考虑使用10元大钞票
money[1]--;
money[0]--;
}else if(money[0]>=3){
money[0]-=3;
}else {
return false;
}
}
}
return true;
}
874,模拟行走机器人
/**
* 机器人在一个无限大小的网格上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令:
* <p>
* -2:向左转 90 度
* -1:向右转 90 度
* 1 <= x <= 9:向前移动 x 个单位长度
* 在网格上有一些格子被视为障碍物。
* <p>
* 第 i 个障碍物位于网格点 (obstacles[i][0], obstacles[i][1])
* <p>
* 机器人无法走到障碍物上,它将会停留在障碍物的前一个网格方块上,但仍然可以继续该路线的其余部分。
* <p>
* 返回从原点到机器人所有经过的路径点(坐标为整数)的最大欧式距离的平方。
* <p>
* 示例 1:
* <p>
* 输入: commands = [4,-1,3], obstacles = []
* 输出: 25
* 解释: 机器人将会到达 (3, 4)
* 示例 2:
* <p>
* 输入: commands = [4,-1,4,-2,4], obstacles = [[2,4]]
* 输出: 65
* 解释: 机器人在左转走到 (1, 8) 之前将被困在 (1, 4) 处
*
* <p>
* 提示:
* <p>
* 0 <= commands.length <= 10000
* 0 <= obstacles.length <= 10000
* -30000 <= obstacle[i][0] <= 30000
* -30000 <= obstacle[i][1] <= 30000
* 答案保证小于 2 ^ 31
* <p>
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/walking-robot-simulation
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*
* @param args
*/
public static void main( String[] args )
{
int[] commands = {4,-1,3};
int[][] obstacles = {};
System.out.println(robotSim( commands,obstacles ));
int[] commands2 = {4,-1,4,-2,4};
int[][] obstacles2 = {{2,4}};
System.out.println(robotSim( commands2,obstacles2 )); //65
int[] commands3 = {1,2,-2,5,-1,-2,-1,8,3,-1,9,4,-2,3,2,4,3,9,2,-1,-1,-2,1,3,-2,4,1,4,-1,1,9,-1,-2,5,-1,5,5,-2,6,6,7,7,2,8,9,-1,7,4,6,9,9,9,-1,5,1,3,3,-1,5,9,7,4,8,-1,-2,1,3,2,9,3,-1,-2,8,8,7,5,-2,6,8,4,6,2,7,2,-1,7,-2,3,3,2,-2,6,9,8,1,-2,-1,1,4,7};
int[][] obstacles3= {{-57,-58},{-72,91},{-55,35},{-20,29},{51,70},{-61,88},{-62,99},{52,17},{-75,-32},{91,-22},{54,33},{-45,-59},{47,-48},{53,-98},{-91,83},{81,12},{-34,-90},{-79,-82},{-15,-86},{-24,66},{-35,35},{3,31},{87,93},{2,-19},{87,-93},{24,-10},{84,-53},{86,87},{-88,-18},{-51,89},{96,66},{-77,-94},{-39,-1},{89,51},{-23,-72},{27,24},{53,-80},{52,-33},{32,4},{78,-55},{-25,18},{-23,47},{79,-5},{-23,-22},{14,-25},{-11,69},{63,36},{35,-99},{-24,82},{-29,-98},{-50,-70},{72,95},{80,80},{-68,-40},{65,70},{-92,78},{-45,-63},{1,34},{81,50},{14,91},{-77,-54},{13,-88},{24,37},{-12,59},{-48,-62},{57,-22},{-8,85},{48,71},{12,1},{-20,36},{-32,-14},{39,46},{-41,75},{13,-23},{98,10},{-88,64},{50,37},{-95,-32},{46,-91},{10,79},{-11,43},{-94,98},{79,42},{51,71},{4,-30},{2,74},{4,10},{61,98},{57,98},{46,43},{-16,72},{53,-69},{54,-96},{22,0},{-7,92},{-69,80},{68,-73},{-24,-92},{-21,82},{32,-1},{-6,16},{15,-29},{70,-66},{-85,80},{50,-3},{6,13},{-30,-98},{-30,59},{-67,40},{17,72},{79,82},{89,-100},{2,79},{-95,-46},{17,68},{-46,81},{-5,-57},{7,58},{-42,68},{19,-95},{-17,-76},{81,-86},{79,78},{-82,-67},{6,0},{35,-16},{98,83},{-81,100},{-11,46},{-21,-38},{-30,-41},{86,18},{-68,6},{80,75},{-96,-44},{-19,66},{21,84},{-56,-64},{39,-15},{0,45},{-81,-54},{-66,-93},{-4,2},{-42,-67},{-15,-33},{1,-32},{-74,-24},{7,18},{-62,84},{19,61},{39,79},{60,-98},{-76,45},{58,-98},{33,26},{-74,-95},{22,30},{-68,-62},{-59,4},{-62,35},{-78,80},{-82,54},{-42,81},{56,-15},{32,-19},{34,93},{57,-100},{-1,-87},{68,-26},{18,86},{-55,-19},{-68,-99},{-9,47},{24,94},{92,97},{5,67},{97,-71},{63,-57},{-52,-14},{-86,-78},{-17,92},{-61,-83},{-84,-10},{20,13},{-68,-47},{7,28},{66,89},{-41,-17},{-14,-46},{-72,-91},{4,52},{-17,-59},{-85,-46},{-94,-23},{-48,-3},{-64,-37},{2,26},{76,88},{-8,-46},{-19,-68}};
System.out.println(robotSim( commands3,obstacles3 )); //5140
}
public static int[][] dist = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; //上 右 下 左(方便旋转)
public static int robotSim( int[] commands, int[][] obstacles )
{
Set<String> set=new HashSet<>( );
for( int i = 0; i < obstacles.length; i++ )
{
set.add( obstacles[i][0]+"+"+obstacles[i][1] );
}
int[] place = new int[2];//位置坐标
int dir=0;//方向
int max=0; //坑,居然不是求最后的值,而是过程中最大值。
for( int i = 0; i < commands.length; i++ )
{
//如果是旋转命令
if( commands[i] == -2 )
{
dir=dir-1>=0?dir-1:3;
}else if( commands[i] == -1 )
{
dir=dir+1<=3?dir+1:0;
}else {
//判断路径上是否有障碍
int command=commands[i];
while( command>0 ){
if(set.contains( (place[0]+dist[dir][0] )+"+"+(place[1]+dist[dir][1]))){
break;
}else {
place[0]+=dist[dir][0];
place[1]+=dist[dir][1];
command--;
}
}
}
max=Math.max( max, (int)Math.pow( place[0],2 )+(int)Math.pow( place[1],2 ));
//System.out.println( Arrays.toString( place ) );
}
return max;
}
944,删列造序
/**
* 给定由 N 个小写字母字符串组成的数组 A,其中每个字符串长度相等。
*
* 你需要选出一组要删掉的列 D,对 A 执行删除操作,使 A 中剩余的每一列
* 都是 非降序 排列的,然后请你返回 D.length 的最小可能值。
*
* 删除 操作的定义是:选出一组要删掉的列,删去 A 中对应列中的所有字符,
* 形式上,第 n 列为 [A[0][n], A[1][n], ..., A[A.length-1][n]])。(可以参见 删除操作范例)
*
*
*
* 示例 1:
* 输入:["cba", "daf", "ghi"]
* 输出:1
* 解释:
* 当选择 D = {1},删除后 A 的列为:["c","d","g"] 和 ["a","f","i"],均为非降序排列。
* 若选择 D = {},那么 A 的列 ["b","a","h"] 就不是非降序排列了。
* 示例 2:
*
* 输入:["a", "b"]
* 输出:0
* 解释:D = {}
* 示例 3:
*
* 输入:["zyx", "wvu", "tsr"]
* 输出:3
* 解释:D = {0, 1, 2}
*
*
* 提示:
*
* 1 <= A.length <= 100
* 1 <= A[i].length <= 1000
*
*
* 删除操作范例:
*
* 比如,有 A = ["abcdef", "uvwxyz"],
*
*
*
* 要删掉的列为 {0, 2, 3},删除后 A 为["bef", "vyz"], A 的列分别为["b","v"], ["e","y"], ["f","z"]。
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/delete-columns-to-make-sorted
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
* @param args
*
*
* 用例子来说的话,设数列bai{an}
* 若符合a(n+1)>an,则du数列的递zhi增的,也是升序的
* 若符合a(n+1)<an,则数列的递减的,也是降序的
* 若符合a(n+1)≤an,则数列是非升序的
* 若符合a(n+1)≥an,则数列是非降序的
*/
public static void main( String[] args )
{
String[] A={"cba", "daf", "ghi"};
System.out.println(minDeletionSize( A ));
String[] A1={"a", "b"};
System.out.println(minDeletionSize( A1 ));
String[] A2={"zyx", "wvu", "tsr"};
System.out.println(minDeletionSize( A2 ));
String[] A3={"rrjk","furt","guzm"};
System.out.println(minDeletionSize( A3 )); //2
}
public static int minDeletionSize(String[] A) {
int count=0;
for( int i = 0; i <A[0].length() ; i++ )
{
char pre=A[0].charAt( i );
for( int j = 1; j <A.length ; j++ )
{
if(A[j].charAt( i )>=pre){ //满足条件
pre=A[j].charAt( i );
}else {
count++;
break;
}
}
}
return count;
}
1005,K 次取反后最大化的数组和
问题描述:
给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)
以这种方式修改数组后,返回数组可能的最大和。
示例 1:
输入:A = [4,2,3], K = 1
输出:5
解释:选择索引 (1,) ,然后 A 变为 [4,-2,3]。
示例 2:
输入:A = [3,-1,0,2], K = 3
输出:6
解释:选择索引 (1, 2, 2) ,然后 A 变为 [3,1,0,2]。
测试代码及答案:
public static void main( String[] args )
{
int[] A={4,2,3};
System.out.println(largestSumAfterKNegations( A,1 ));
int[] A2={3,-1,0,2};
System.out.println(largestSumAfterKNegations( A2,3 ));
int[] A3={2,-3,-1,5,-4};
System.out.println(largestSumAfterKNegations( A3,2 ));
int[] A4={-2,9,9,8,4};
System.out.println(largestSumAfterKNegations( A4,5 ));
}
//贪心思路:
//1,排序
//2,首先把负数按优先级转换为正数。
//3,去反复翻转同一个全局最小值。
//4, 注意0存在。有0就一直翻转0
//5,在出现正数时.前一位和当前位存在全局最小值。
public static int largestSumAfterKNegations( int[] A, int K ) {
Arrays.sort( A );
//System.out.println(Arrays.toString( A ));
int index = 0;
int sum = 0;
int mix;
for( int i = 0; i < K; i++ ){
if( A[index] < 0 ){
A[index] = -A[index];
}
else if( A[index] > 0 ){
//直接用全局最小值计算最后翻转结果
mix = Math.min( A[index], index >0 ? A[index - 1] : 10001 );
//由于目前数组全为正数,计算最后翻转是否得到负数,是则先减去两倍最小负数。
sum -= (K - i) % 2 == 1 ? 2 * mix : 0;
break;
}else { //0 直接停止
break;
}
if( index < A.length - 1 ){
index++;
}
}
for( int i = 0; i < A.length; i++ ){
sum += A[i];
}
return sum;
}
1046,最后一块石头的重量
问题描述:
有一堆石头,每块石头的重量都是正整数。
每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。
示例:
输入:[2,7,4,1,8,1]
输出:1
解释:
先选出 7 和 8,得到 1,所以数组转换为 [2,4,1,1,1],
再选出 2 和 4,得到 2,所以数组转换为 [2,1,1,1],
接着是 2 和 1,得到 1,所以数组转换为 [1,1,1],
最后选出 1 和 1,得到 0,最终数组转换为 [1],这就是最后剩下那块石头的重量。
提示:
1 <= stones.length <= 30
1 <= stones[i] <= 1000
问题解答:
public static int lastStoneWeight(int[] stones) {
//先用list来做,先排序
Arrays.sort( stones );
ArrayList<Integer> list=new ArrayList<>( );
for( int i = 0; i < stones.length; i++ )
{
list.add( stones[i] );
}
while( list.size()>1 ){
int len=list.size();
int last=list.get( len-1 )-list.get( len-2 );
list.remove( list.size()-1);
list.remove( list.size()-1);
if(last!=0){
list.add( last );
Collections.sort( list );
}
}
return list.size()>0?list.get( 0 ):0;
}
1403,非递增顺序的最小子序列
/**
* 给你一个数组 nums,请你从中抽取一个子序列,满足该子序列的元素之和 严格 大于未包含在该子序列中的各元素之和。
*
* 如果存在多个解决方案,只需返回 长度最小 的子序列。如果仍然有多个解决方案,则返回 元素之和最大 的子序列。
*
* 与子数组不同的地方在于,「数组的子序列」不强调元素在原数组中的连续性,也就是说,
* 它可以通过从数组中分离一些(也可能不分离)元素得到。
*
* 注意,题目数据保证满足所有约束条件的解决方案是 唯一 的。同时,返回的答案应当按 非递增顺序 排列。
*
*
*
* 示例 1:
*
* 输入:nums = [4,3,10,9,8]
* 输出:[10,9]
* 解释:子序列 [10,9] 和 [10,8] 是最小的、满足元素之和大于其他各元素之和的子序列。但是 [10,9] 的元素之和最大。
* 示例 2:
*
* 输入:nums = [4,4,7,6,7]
* 输出:[7,7,6]
* 解释:子序列 [7,7] 的和为 14 ,不严格大于剩下的其他元素之和(14 = 4 + 4 + 6)。
* 因此,[7,6,7] 是满足题意的最小子序列。注意,元素按非递增顺序返回。
* 示例 3:
*
* 输入:nums = [6]
* 输出:[6]
*
*
* 提示:
*
* 1 <= nums.length <= 500
* 1 <= nums[i] <= 100
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/minimum-subsequence-in-non-increasing-order
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public static void main( String[] args )
{
int[] nums={4,3,10,9,8};
System.out.println(minSubsequence( nums ));
}
public static List<Integer> minSubsequence(int[] nums) {
Arrays.sort( nums );
int sum=0;
for( int i = 0; i <nums.length ; i++ )
{
sum+=nums[i];
}
ArrayList<Integer> list=new ArrayList<>( );
int sum2=0;
for( int i = nums.length-1; i >=0; i-- )
{
list.add( nums[i] );
sum2+=nums[i];
if( sum2>sum/2 ){
break;
}
}
return list;
}
1518,换酒问题
问题描述:
小区便利店正在促销,用 numExchange 个空酒瓶可以兑换一瓶新酒。你购入了 numBottles 瓶酒。
如果喝掉了酒瓶中的酒,那么酒瓶就会变成空的。
请你计算 最多 能喝到多少瓶酒。
示例 1:
输入:numBottles = 9, numExchange = 3
输出:13
解释:你可以用 3 个空酒瓶兑换 1 瓶酒。
所以最多能喝到 9 + 3 + 1 = 13 瓶酒。
示例 2:
输入:numBottles = 15, numExchange = 4
输出:19
解释:你可以用 4 个空酒瓶兑换 1 瓶酒。
所以最多能喝到 15 + 3 + 1 = 19 瓶酒。
示例 3:
输入:numBottles = 5, numExchange = 5
输出:6
示例 4:
输入:numBottles = 2, numExchange = 3
输出:2
测试案例与解答:
public static void main( String[] args )
{
System.out.println(numWaterBottles( 9,3 ));
System.out.println(numWaterBottles( 15,4 ));
System.out.println(numWaterBottles( 5,5 ));
}
public static int numWaterBottles(int numBottles, int numExchange) {
int sum=numBottles;
while( numBottles>=numExchange ){
int add=numBottles/numExchange; //新换的酒
sum+=add;
numBottles=numBottles-add*numExchange+add;
}
return sum;
}