非力扣100原题

发布于:2025-09-04 ⋅ 阅读:(16) ⋅ 点赞:(0)

 多线程交替打印0-100

2个线程交替打印0-100
public class Main {

    private static final Object LOCK = new Object();
    private static volatile int count = 0;
    private static final int MAX = 100;

    public static void main(String[] args) {
        Thread thread = new Thread(new Seq(0));
        Thread thread1 = new Thread(new Seq(1));
        thread.start();
        thread1.start();
    }

    static class Seq implements Runnable {
        private final int index;

        public Seq(int index) {
            this.index = index;
        }

        @Override
        public void run() {
            // Run方法只要执行结束了,线程就结束了
            while (count < MAX) {
                // 同步代码块,一个时刻只能有一个线程获取到锁
                synchronized (LOCK) {
                    // 获取到锁就进来判断,当前是否轮到该线程打印
                    while (count % 2 != index) {
                        // 不是当前线程打印,那么就让当前线程去wait,它会自动释放锁,所以其他线程可以进来
                        try {
                            LOCK.wait();
                            // 当线程被唤醒时,会尝试重新进入synchronized代码块
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    // 是当前线程打印, 但count>MAX
                    if (count > MAX) {
                        LOCK.notifyAll();
                        return;
                    }
                    System.out.println("Thread-" + index + ":" + count);
                    count++;
                    LOCK.notifyAll();
                }
            }
        }
    }
}
public class Main {

    private static final Object LOCK = new Object();
    private static volatile int count = 0;
    private static final int MAX = 100;

    public static void main(String[] args) {
        Thread thread = new Thread(new Seq(0));
        Thread thread1 = new Thread(new Seq(1));
        Thread thread2 = new Thread(new Seq(2));
        thread.start();
        thread1.start();
        thread2.start();
    }

    static class Seq implements Runnable {
        private final int index;

        public Seq(int index) {
            this.index = index;
        }

        @Override
        public void run() {
            // Run方法只要执行结束了,线程就结束了
            while (count < MAX) {
                // 同步代码块,一个时刻只能有一个线程获取到锁
                synchronized (LOCK) {
                    // 获取到锁就进来判断,当前是否轮到该线程打印
                    while (count % 3 != index) {
                        // 不是当前线程打印,那么就让当前线程去wait,它会自动释放锁,所以其他线程可以进来
                        try {
                            LOCK.wait();
                            // 当线程被唤醒时,会尝试重新进入synchronized代码块
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    // 是当前线程打印, 但count>MAX
                    if (count > MAX) {
                        LOCK.notifyAll();
                        return;
                    }
                    System.out.println("Thread-" + index + ":" + count);
                    count++;
                    LOCK.notifyAll();
                }
            }
        }
    }
}

多线程交替打印ABC

import java.util.concurrent.Semaphore;
// 多线程打印ABC
public class Printer {
    private final Semaphore semA = new Semaphore(1); // 信号量A设置为1,从A开始打印
    private final Semaphore semB = new Semaphore(0);
    private final Semaphore semC = new Semaphore(0);
    private static int n = 3;   // 打印轮次

    public static void main(String[] args) {
        Printer printer = new Printer();
        new Thread(()->printer.print('A',printer.semA,printer.semB)).start();
        new Thread(()->printer.print('B',printer.semB,printer.semC)).start();
        new Thread(()->printer.print('C',printer.semC,printer.semA)).start();
    }
    public void print(char ch, Semaphore current, Semaphore next) {
        try {
            for (int i = 0; i < n; i++) {
                current.acquire();  // 获取当前信号量
                System.out.println(Thread.currentThread().getName() + ": " + ch);
                next.release();     // 释放下一个信号量
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

奇偶交换

给定数组,奇数在前,偶数在后

import java.util.Arrays;
public class Solution {
    public static int[] jiaohuang(int[] nums){
        if(nums.length<2||nums == null){
            return nums;
        }

        int left = 0;
        int right = nums.length-1;
        while (left<right){
            //  选定偶数
            while (left<right && nums[left] % 2 !=0){
                left++;
            }
            //  选定奇数
            while (left<right && nums[right]%2 == 0){
                right--;
            }
            if(left < right){
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left++;
                right--;
            }
        }
        return nums;
    }

    public static void main(String[] args){
        Solution solution  = new Solution();
        int[] nums = {1,2,3,4};
        int[] result = solution.jiaohuang(nums);
        System.out.print(Arrays.toString(nums));
    }
}

字典序的第k小数字

// 字典序:数字的前缀进行排序,如10<9,因为10的前缀是1<9
// 数组{1,2,-,9,10,11,12}-->{1,10,11,12,2,--,9}
// 思路:当前指针+前缀数(非指针概念),当成一个(key,value)形式,cur为key,value = 前缀数
// 如果当前指针<目标指针,while循环,
// 计算当前数的节点数(如1-201,那么在1和2之间隔着10-19,100-199:节点数为1+10+10*10)
// 如果 当前指针 + 当前前缀节点 <=k,即不在k的范围内,那么当前指针(下个前缀节点) = 当前指针 + 当前前缀节点,前缀数++
// else,在k的范围内,那么当前指针 = cur指针+1,前缀数*10更加细分
//(其实这里有点无限迭代的意思,判断在10-19区间还是继续细分在100-109~190-199区间,但n是固定的,有限迭代)
public int findKthNumber(int n, int k) {
         long cur = 1; // 当前指针对应
         long prix = 1; // 当前前缀数,可以把当成一个(key,value)形式,cur为key,value = 前缀数
         while (cur < k){
             long prixNum = getCount(prix,n);// 当前前缀节点数量
             // k不在当前前缀数
             if(cur+prixNum <= k){
                 cur+=prixNum; // 下个指针 = 当前指针+节点数
                 prix++; // 前缀数++
             }else {
                 cur++; // 在当前前缀循环,从1变成10,指针从索引0(1)到索引1(10)
                 prix*=10; // 前缀细分
             }
         }
         return (int)prix;
    }
    // 当前前缀下的所有子节点数总和=下一个前缀的起点-当前前缀的起点
    public long getCount(long prix,long n){
        long count = 0;// 节点数量
        long prixNext = prix+1; // 下一个前缀数
        while (prix <= n){
            count += Math.min(n-1,prixNext)-prix;
            prix*=10;
            prixNext*=10;
        }
        return count;
    }

带TTL的LRU缓存

相对于LRU:有一个时间字段ttl,需要改变的是put方法,仅在node不为空时,覆盖时间值,记得加上系统当前时间;在getNode方法中判断,当前节点是否过期,过期则移除节点以及对应的map的key,并返还为空

public class Solution {
    static class Node{
        int key,value;
        long expireTime;// 预定过期时间
        Node prev,next;

        Node(int key,int value,long ttl){
            this.key = key;
            this.value = value;
            this.expireTime = System.currentTimeMillis() + ttl;
        }
    }

    static class LRUCacheTTL{
        private  final int capacity;
        private final Node dummy = new Node(-1,-1,0);
        private final Map<Integer,Node> map = new HashMap<>();

        LRUCacheTTL(int capacity) {
            this.capacity = capacity;
            dummy.prev = dummy;
            dummy.next = dummy;

        }

        public int get(int key){
            Node node = getNode(key);
            if(node == null){
                return -1;
            }
            return node.value;
        }

        public void put(int key,int value,long ttl){
             Node node = getNode(key);
             if(node != null){
                 node.value = value;
                 node.expireTime = System.currentTimeMillis()+ttl;
             }
             node = new Node(key,value,ttl);
             map.put(key,node);
             pushFront(node);

             if(map.size()>capacity){
                 Node backNode = dummy.prev;
                 remove(backNode);
                 map.remove(backNode.key);
             }

        }

        public Node getNode(int key){
            Node node = map.get(key); // key不存在,返还为null
            if(node == null){
                return null;
            }
            if(node.expireTime <= System.currentTimeMillis()){
                remove(node);
                map.remove(key);
                return null;
            }
            remove(node);
            pushFront(node);
            return node;
        }

        public void remove(Node node){
           node.next.prev = node.prev;
           node.prev.next = node.next;
        }

        public void pushFront(Node node){
            node.prev = dummy;
            node.next = dummy.next;

            dummy.next = node;
            node.next.prev = node;
        }
    }

    public static void main(String[] args) {
        LRUCacheTTL cache = new LRUCacheTTL(2);

        cache.put(1, 1, 3000); // TTL: 3秒
        cache.put(2, 2, 5000); // TTL: 5秒

        System.out.println("get(1): " + cache.get(1)); // 1

        try {
            Thread.sleep(2000); // 等待2秒
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        System.out.println("get(2): " + cache.get(2)); // 2

        try {
            Thread.sleep(3000); // 再等3秒 → key=1 已过期
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        System.out.println("get(1): " + cache.get(1)); // -1 (已过期)

        cache.put(3, 3, 1000); // 触发淘汰,key=2 应该被踢掉
        System.out.println("get(2): " + cache.get(2)); // -1
        System.out.println("get(3): " + cache.get(3)); // 3
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到