阿里二面3道算法题
今天在一个学习群里看到一个小伙伴去面试了阿里本地生活,二面有4道算法编程题,我们一起来看下难度,我就纳闷了,明明有算法岗,还要求我们这些码农会算法干啥子。毕竟术业有专攻,这是人家的饭碗
1分割平衡字符串
题目描述
在一个「平衡字符串」中,‘L’ 和 ‘R’ 字符的数量是相同的。
给出一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串。
返回可以通过分割得到的平衡字符串的最大数量。
示例 1:
输入:s = “RLRRLLRLRL”
输出:4
解释:s 可以分割为 “RL”, “RRLL”, “RL”, “RL”, 每个子字符串中都包含相同数量的 ‘L’ 和 ‘R’。
示例 2:
输入:s = “RLLLLRRRLR”
输出:3
解释:s 可以分割为 “RL”, “LLLRRR”, “LR”, 每个子字符串中都包含相同数量的 ‘L’ 和 ‘R’。
示例 3:
输入:s = “LLLLRRRR”
输出:1
解释:s 只能保持原样 “LLLLRRRR”.
提示:
1 <= s.length <= 1000
s[i] = ‘L’ 或 ‘R’
分割得到的每个字符串都必须是平衡字符串。
解题思路
遍历字符串,使用一个变量 imbalance 来记录字符串是否达到平衡,遇到’L’,isbalance 加一,遇到’R’,imbalance 减一,当 imbalance 为 0 的时候,这个字符串即为平衡字符串。
复杂度分析
时间复杂度:O(n),其中 n 为字符串 s 的长度。
空间复杂度:O(1)。
代码实现
class Test{
public int balancedStringSplit(String s) {
//输出的总数量
int count= 0;
//是否平衡的标识,为0 时是平衡的
int imbalance = 0;
for (int i = 0; i < s.length(); i ++) {
if (s.charAt(i) == ‘L’) {
isbalance++;
} else {
isbalance–;
}
if (isbalance== 0) {
count++;
}
}
return count;
}
}
2 给出一个数和一个数组,求数组中连续元素的和与给出的数相等的子集合,例如7和int base[] = {1, 4, 2, 3, 4, 3, 6, 7, 8, 9};输出[1,32],[3,4],[4,3],[7]
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int base[] = {1, 4, 2, 3, 4, 3, 6, 7, 8, 9};
while (true) {
StringBuffer sb = new StringBuffer();
int guest = scanner.nextInt();
int sum = 0;
for (int i = 0; i < base.length; i++) {
List tempBox = new ArrayList<>();
sum = base[i];
tempBox.add(base[i]);
//这个是考虑直接等于7的情况
if (sumguest){
sb.append(tempBox.toString());
continue;
}
for (int j = i+1; j < base.length; j++) {
tempBox.add(base[j]);
//这个是考虑2者相加等于7的情况
sum += base[j];
if (sumguest) {
sb.append(tempBox.toString());
}
}
}
System.out.println(sb.toString());
}
}
3写一个基于链表的栈
不是有人还不知道栈是什么吧?我用简单的一句话概括下:
吃多了拉就是队列,吃多了吐就是栈,换言之,先进先出的是队列,先进后出的就是栈,这道题重点在于考察链表反转
public class Linked {
private Node<T> first;
private Node<T> tail;
public Linked() {
first = new Node<T>();
tail = first;
}
public class Node<T>{
private Node next;
private Node pre;
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
public void setNext(Node next) {
this.next = next;
}
public Node getPre() {
return pre;
}
public void setPre(Node pre) {
this.pre = pre;
}
}
public void push(T obj){
Node<T> node = new Node();
node.setObj(obj);
node.pre= tail;
tail.next =node;
tail = node;
}
public T pop(){
if (tail.pre ==null){
return null;
}
T obj = tail.getObj();
tail = tail.pre;
tail.next =null;
return obj;
}
}
测试代码
public void test2(){
Linked<String> linked = new Linked<>();
System.out.print("入栈:");
for (int i =0;i<10;i++){
linked.push(i+"");
System.out.print(i+" ");
}
System.out.println();
System.out.println("出栈");
for(int i = 0 ;i<10;i++){
System.out.println(linked.pop());
}
4 启动3个线程,第一个线程打印0,第二个打印1,第三个打印2,依次类推,打印到20为止
这道题终点在于考察多线程情况下,线程等待和唤醒的时机与对同一个资源加互斥锁
public class TestReentranTLock {
//自己写的demo
int num = -1;
int index = 0;
Lock lock = new ReentrantLock(true);
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
void thread1(){
int threadIndex = Integer.parseInt(Thread.currentThread().getName());
try{
lock.lock();
while(threadIndex != index){
c1.await();
}
System.out.print(Thread.currentThread().getName() + " : ");
System.out.print(++num + ",");
System.out.println();
}catch(Exception e){
e.printStackTrace();
}finally{
index = (index + 1) % 3;
c2.signalAll();
c3.signalAll();
lock.unlock();
}
}
void thread2(){
int threadIndex = Integer.parseInt(Thread.currentThread().getName());
try{
lock.lock();
while(threadIndex != index){
c2.await();
}
System.out.print(Thread.currentThread().getName() + " : ");
System.out.print(++num + ",");
System.out.println();
}catch(Exception e){
e.printStackTrace();
}finally{
index = (index + 1) % 3;
c1.signalAll();
c3.signalAll();
lock.unlock();
}
}
void thread3(){
int threadIndex = Integer.parseInt(Thread.currentThread().getName());
try{
lock.lock();
while(threadIndex != index){
c3.await();
}
System.out.print(Thread.currentThread().getName() + " : ");
System.out.print(++num + ",");
System.out.println();
}catch(Exception e){
e.printStackTrace();
}finally{
index = (index + 1) % 3;
c2.signalAll();
c1.signalAll();
lock.unlock();
}
}
public static void main(String[] args) {
final TestReentranTLock testReentranTLock = new TestReentranTLock();
new Thread(new Runnable() {
@Override
public void run() {
//考虑到0到20,3个线程只需要循环7次
for(int j=0;j<7;j++) {
testReentranTLock.m1();
}
}
}, "1号线程").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<7;j++) {
testReentranTLock.m2();
}
}
}, "2号线程").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<7;j++) {
testReentranTLock.m3();
}
}
}, "3号线程").start();
}
}