2023.1.1 2351.第一个出现的字母:
给你一个由小写英文字母组成的字符串 s ,请你找出并返回第一个出现两次的字母
注意:
- 如果 a 的第二次出现比b的第二次出现在字符串中的位置更靠前,则认为字母a在字母b之前出现两次
- s包含至少一个出现两次的字母
- 示例:输入:s=“abcdd”
- 输出:“d”
//哈希表
char repeatedCharacter(char * s){
int hash[26] = {0};//数组哈希表
for (int i = 0; i < strlen(s); ++i) {//枚举字符串每一个字符
if (++hash[s[i] - 'a'] >= 2) {//记录出现次数
return s[i];
}
}
return -1;
}
//哈希表
char repeatedCharacter(char * s) {
int seen[26];
memset(seen, 0, sizeof(seen));
for (int i = 0; s[i] != '\0'; i++) {
if (seen[s[i] - 'a'] > 0) {
return s[i];
}
seen[s[i] - 'a'] = 1;
}
return ' ';
}
2023.1.2 1801.积压订单中的订单总数:
class Solution:
def getNumberOfBacklogOrders(self, orders: List[List[int]]) -> int:
buybacklog = []
sellbacklog = []
MOD = 10 ** 9 + 7
n = len(orders)
for i in range(n):#遍历输入的订单
if orders[i][2] == 0:#采购订单
while orders[i][1] and sellbacklog and sellbacklog[0][0] <= orders[i][0]:
#当采购订单数量不为0,小堆栈中销售订单最低价格小于采购订单价格时
if sellbacklog[0][1] > orders[i][1]:#如果销售订单数量大于采购订单数量
sellbacklog[0][1] -= orders[i][1]#用销售订单数减去采购订单数
orders[i][1] = 0#采购订单数归0
break
orders[i][1] -= sellbacklog[0][1]
#如果销售订单数量小于等于采购订单数量,用采购订单数减去销售订单数
heapq.heappop(sellbacklog)#将销售订单最低价格的订单弹出
if orders[i][1]:#如果采购订单数大于0
heapq.heappush(buybacklog, [-orders[i][0], orders[i][1]])
#将采购订单推入大堆栈,则此时价格应取负
elif orders[i][2] == 1:
while orders[i][1] and buybacklog and -buybacklog[0][0] >= orders[i][0]:
#大堆栈中价格取负
if buybacklog[0][1] > orders[i][1]:
buybacklog[0][1] -= orders[i][1]
orders[i][1] = 0
break
orders[i][1] -= buybacklog[0][1]
heapq.heappop(buybacklog)
if orders[i][1]:
heapq.heappush(sellbacklog, [orders[i][0], orders[i][1]])
#销售订单推入小堆栈不用取负
return (sum(x for _, x in buybacklog) + sum(x for _, x in sellbacklog)) % MOD
2023.1.3 2042.检查句子中的数字是否递增
//模拟
bool areNumbersAscending(char * s) {
int pre = 0, pos = 0;//pre记录前一个整数
while (s[pos] != '\0') {
if (isdigit(s[pos])) {
int cur = 0;
while (s[pos] != '\0' && isdigit(s[pos])) {
//由于每个token要么是由0-9组成的正整数要么是字母,当该整数为两位数及以上时就需要把前一个数字先乘10再加下一位数字
cur = cur * 10 + s[pos] - '0';//将字符转换为十进制整数
pos++;
}
if (cur <= pre) {//如果该整数小于记录的前一个整数
return false;
}
pre = cur;//否则把该整数赋值给pre
} else {
pos++;//如果不是整数
}
}
return true;
}
2023.1.4 1802.有界数组中指定下标处的最大值
思路:
最值问题考虑贪心算法,指定下标处要最大化,则可以通过二分法找出符合条件的有效元素值,根据贪心算法,该值要符合的条件是,从该值向左向右递减且保证相差的绝对值都是1,且最终数组元素和不大于maxsum
- 向左向右递减有两种情况:
- 1.如果指定下标index位置处到边界的距离length大于等于选取的有效元素值x,那么会出现x递减之后会出现减到0的情况,那么对于距离大于x的位置,就放置最小值1
- 2.index位置到边界的距离小于x,递减即可
- 第二种情况以 5为有效元素值为例 从5到最后边界:5 4 3 2 ,big=5,length=3,有length+1<big的规律,减到边界值small为big-length=2,有等差数列求和返回左边或右边的数组元素和(不包括有效元素值)
- 第一种情况以5 4 3 2 1 1 1为例,big=5,length=6,有length+1>(=)big的规律,big递减到1后面值全为1,后面的值的和为ones=length-(big-1)=2,同样进行等差求和(不包括有效元素值)
long cal(int big,int length){//big为指定下标处元素的最大值,length为到边界的距离
if(length + 1 < big){//如果是第二种情况
int small = big - length;
return (long) (big - 1 + small) *length /2;//等差数列求和
}
else {//第一种情况
int ones = length - (big - 1);
return (long) big * (big - 1) / 2 +ones;
}
}
boll valid(int mind,int n,int index,int maxsum){//判断选择的值是否有效
int left = index;
int right = n- index - 1;
//数组元素和=当前位置值+左边和+右边和
return (mid + cal(mid,left)+cal(mid,right)) <=maxsum;
}
int maxvalue(int n,int index,int maxsum){//二分法选择元素值
int left = 1,right = maxsum;//选择的值一定在1和maxsum之间
while(left < right){//多次选值,选出最大化的值
int mid = (left + right + 1) / 2;//向上取整
if(valid(mid,n,index,maxsum)){//进行判断,如果有效
left = mid;//将left赋值为该值,由于最后返回的是left,所以不用加1
}else{//如果无效
right = mid - 1;//将right赋值为该值-1,从该值的左侧第一个值开始
}
}
return left;
}