Leetcode 432~438题

第四百三十二题:

class AllOne {
public:
    struct Node {
        Node *left, *right;
        int val;
        unordered_set<string> S;

        Node (int _val) {
            val = _val;
            left = right = NULL;
        }
    }*left, *right;
    unordered_map<string, Node*> hash;

    /** Initialize your data structure here. */
    AllOne() {
        left = new Node(INT_MIN), right = new Node(INT_MAX);
        left->right = right, right->left = left;
    }

    Node* add_to_right(Node* node, string key, int val) {
        if (node->right->val == val) node->right->S.insert(key);
        else {
            auto t = new Node(val);
            t->S.insert(key);
            t->right = node->right, node->right->left = t;
            node->right = t, t->left = node;
        }
        return node->right;
    }

    Node* add_to_left(Node* node, string key, int val) {
        if (node->left->val == val) node->left->S.insert(key);
        else {
            auto t = new Node(val);
            t->S.insert(key);
            t->left = node->left, node->left->right = t;
            node->left = t, t->right = node;
        }
        return node->left;
    }

    void remove(Node* node) {
        node->left->right = node->right;
        node->right->left = node->left;
        delete node;
    }

    /** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
    void inc(string key) {
        if (hash.count(key) == 0) hash[key] = add_to_right(left, key, 1);
        else {
            auto t = hash[key];
            t->S.erase(key);
            hash[key] = add_to_right(t, key, t->val + 1);
            if (t->S.empty()) remove(t);
        }
    }

    /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
    void dec(string key) {
        if (hash.count(key) == 0) return;
        auto t = hash[key];
        t->S.erase(key);
        if (t->val > 1) {
            hash[key] = add_to_left(t, key, t->val - 1);
        } else {
            hash.erase(key);
        }
        if (t->S.empty()) remove(t);
    }

    /** Returns one of the keys with maximal value. */
    string getMaxKey() {
        if (right->left != left) return *right->left->S.begin();
        return "";
    }

    /** Returns one of the keys with Minimal value. */
    string getMinKey() {
        if (left->right != right) return *left->right->S.begin();
        return "";
    }
};

/**
 * Your AllOne object will be instantiated and called as such:
 * AllOne* obj = new AllOne();
 * obj->inc(key);
 * obj->dec(key);
 * string param_3 = obj->getMaxKey();
 * string param_4 = obj->getMinKey();
 */
public class AllOne {
    /**
     * k-v查找节点
     */
    private final Map<String, ListNode> map = new HashMap<>();
    /**
     * key - 节点的值;
     * value - 链表中第一个值为key的节点。
     */
    private final Map<Integer, ListNode> first = new HashMap<>();
    /**
     * key - 节点的值;
     * value - 链表中最后一个值为key的节点。
     */
    private final Map<Integer, ListNode> last = new HashMap<>();

    /**
     * 链表伪头节点
     */
    private final ListNode head = new ListNode(null, 0);
    /**
     * 链表伪尾节点
     */
    private final ListNode tail = new ListNode(null, 0);

    AllOne() {
        head.next = tail;
        tail.prev = head;
    }

    private class ListNode { // 链表节点
        ListNode prev, next;
        String key;
        int val;

        public ListNode(String key, int val) {
            this.key = key;
            this.val = val;
        }
    }

    /**
     * 将节点 [insert] 插入到 n1 与 n2 之间
     */
    private void insert(ListNode n1, ListNode n2, ListNode insert) {
        n1.next = insert;
        n2.prev = insert;
        insert.prev = n1;
        insert.next = n2;
    }

    /**
     * 删除链表节点[n]
     */
    private void remove(ListNode n) {
        ListNode prev = n.prev;
        ListNode next = n.next;
        prev.next = next;
        next.prev = prev;
        n.prev = null;
        n.next = null;
    }

    /**
     * 将节点node移动到prev与next之间
     */
    private void move(ListNode node, ListNode prev, ListNode next) {
        remove(node);
        insert(prev, next, node);
    }

    /**
     * 将[node]设置为新的val值起始点
     */
    private void newFirst(int val, ListNode node) {
        first.put(val, node);
        if (!last.containsKey(val)) last.put(val, node);
    }

    /**
     * 将[node]设置为新的val值终止点
     */
    private void newLast(int val, ListNode node) {
        last.put(val, node);
        if (!first.containsKey(val)) first.put(val, node);
    }

    /**
     * Inserts a new key <Key> with value 1. Or increments an existing key by 1.
     * <p>
     * 值加一后,当前节点会往左移动。
     * 如果当前key不存在,那就把这个节点插入到链表尾部.
     */
    public void inc(String key) {
        if (!map.containsKey(key)) { // 当前key不存在,插入到链表末尾
            ListNode node = new ListNode(key, 1);
            map.put(key, node);
            insert(tail.prev, tail, node); // 插入
            if (!first.containsKey(1)) newFirst(1, node); // 更新first
            newLast(1, node); // 更新last
        } else {
            ListNode node = map.get(key); // 当前节点
            int val = node.val; // 旧值
            int newVal = val + 1; // 新值
            ListNode firstNode = first.get(val); // 链表中第一个值为val的节点
            ListNode lastNode = last.get(val); // 链表中最后一个值为val的节点

            // 1. 找位置
            node.val = newVal;
            if (firstNode == lastNode) { // 当前节点是唯一一个值为val的节点
                first.remove(val); // 没有值为val的节点了
                last.remove(val); // 没有值为val的节点了
                newLast(newVal, node); // 更新last
            } else if (node == firstNode) { // 该节点是链表中第一个值为val的节点
                // 不动
                newLast(newVal, node);
                newFirst(val, node.next);
            } else {
                if (node == lastNode) newLast(val, node.prev); // 是最后一个值val的节点
                // 这个时候,节点应该移动到链表中第一个值为val的节点之前
                move(node, firstNode.prev, firstNode);
                newLast(newVal, node);
            }
        }
    }

    /**
     * Decrements an existing key by 1. If Key's value is 1, remove it from the data structure.
     * 
     * 值减一之后,节点在链表中的位置会往右移动
     */
    public void dec(String key) {
        // 与inc类似,不过多了一个值为1删除的判断
        ListNode node = map.get(key);
        if (node == null) return;

        int val = node.val;
        int newVal = val - 1;
        ListNode firstNode = first.get(val);
        ListNode lastNode = last.get(val);

        if (val == 1) { // 值为1,删除这个节点
            if (firstNode == lastNode) { // 没有值为1的节点了
                first.remove(1);
                last.remove(1);
            } else if (node == firstNode) { // 起始值右移
                first.put(1, node.next);
            } else if (node == lastNode) { // 终结值左移
                last.put(1, node.prev);
            }
            remove(node);
            map.remove(key);
        } else {
            node.val = newVal;
            if (firstNode == lastNode) { // 唯一值为val的节点
                // 位置不变,成为newVal的首位
                first.remove(val);
                last.remove(val);
                newFirst(newVal, node);
            } else if (node == lastNode) { // 是最后一项val值的节点
                // 位置不变,成为newVal的首位,并且prev成为val的最后一位
                newFirst(newVal, node);
                newLast(val, node.prev);
            } else {
                if (node == firstNode) newFirst(val, node.next); // 是第一项val值的节点
                move(node, lastNode, lastNode.next); // 移动到lastNode之后
                newFirst(newVal, node);
            }
        }
    }

    /**
     * Returns one of the keys with maximal value.
     * 返回链表头
     */
    public String getMaxKey() {
        return head.next == tail ? "" : head.next.key;
    }

    /**
     * Returns one of the keys with Minimal value.
     * 返回链表尾
     */
    public String getMinKey() {
        return tail.prev == head ? "" : tail.prev.key;
    }
}
class KeyNode:
    
    def __init__(self, key):
        self.key = key
        self.prev = None
        self.next = None

class KeyList:
    
    def __init__(self):
        self.keyNode = {}
        self.keyHead = KeyNode("")
        self.keyTail = KeyNode("")
        self.keyHead.next = self.keyTail
        self.keyTail.prev = self.keyHead
    
    def isEmpty(self):
        return not self.keyNode
    
    def add(self, key):
        newNode = KeyNode(key)
        newNode.prev, newNode.next = self.keyHead, self.keyHead.next
        self.keyHead.next.prev = newNode
        self.keyHead.next = newNode
        self.keyNode[key] = newNode
    
    def remove(self, key):
        delNode = self.keyNode[key]
        delNode.prev.next, delNode.next.prev = delNode.next, delNode.prev
        del self.keyNode[key]
    
    
class CountNode:
    
    def __init__(self, count):
        self.count = count
        self.keyList = KeyList()
        self.prev = None
        self.next = None
    
    def isEmpty(self):
        return self.keyList.isEmpty()
    
    def add(self, key):
        self.keyList.add(key)
    
    def remove(self, key):
        self.keyList.remove(key)
    
    def getKey(self):
        return self.keyList.keyHead.next.key

        

class CountList:
    
    def __init__(self):
        self.keyCountNode = {}
        self.countHead = CountNode(-1)
        self.countTail = CountNode(-1)
        self.countHead.next = self.countTail
        self.countTail.prev = self.countHead
    
    def isEmpty(self):
        return not self.keyCountNode
    
    def add(self, key):
        if key not in self.keyCountNode:
            if self.countHead.next.count == 1:
                self.countHead.next.add(key)
            else:
                oneCount = CountNode(1)
                oneCount.add(key)
                oneCount.prev, oneCount.next = self.countHead, self.countHead.next
                self.countHead.next.prev, self.countHead.next = oneCount, oneCount
            self.keyCountNode[key] = self.countHead.next
        else:
            countNode = self.keyCountNode[key]
            moreCount = countNode.count + 1
            if countNode.next.count == moreCount:
                countNode.next.add(key)
                self.keyCountNode[key] = countNode.next
            else:
                newNode = CountNode(moreCount)
                newNode.add(key)
                newNode.prev, newNode.next = countNode, countNode.next
                countNode.next.prev, countNode.next = newNode, newNode
                self.keyCountNode[key] = newNode
            
            countNode.remove(key)
            if countNode.isEmpty():
                countNode.prev.next, countNode.next.prev = countNode.next, countNode.prev
        
    
    def remove(self, key):
        countNode = self.keyCountNode[key]
        lessCount = countNode.count - 1
        if countNode.prev.count == lessCount:
            countNode.prev.add(key)
            self.keyCountNode[key] = countNode.prev
        elif lessCount != 0:
            newNode = CountNode(lessCount)
            newNode.add(key)
            newNode.prev, newNode.next = countNode.prev, countNode
            countNode.prev.next, countNode.prev = newNode, newNode
            self.keyCountNode[key] = newNode
        else:
            del self.keyCountNode[key]
        
        countNode.remove(key)
        if countNode.isEmpty():
            countNode.prev.next, countNode.next.prev = countNode.next, countNode.prev
    

class AllOne:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.countList = CountList()
        

    def inc(self, key: str) -> None:
        """
        Inserts a new key <Key> with value 1. Or increments an existing key by 1.
        """
        self.countList.add(key)

    def dec(self, key: str) -> None:
        """
        Decrements an existing key by 1. If Key's value is 1, remove it from the data structure.
        """
        if key not in self.countList.keyCountNode:
            return
        self.countList.remove(key)


    def getMaxKey(self) -> str:
        """
        Returns one of the keys with maximal value.
        """
        if self.countList.isEmpty():
            return ""
        return self.countList.countTail.prev.getKey()

    def getMinKey(self) -> str:
        """
        Returns one of the keys with Minimal value.
        """
        if self.countList.isEmpty():
            return ""
        return self.countList.countHead.next.getKey()
type AllOne struct {
	H     map[string]*DoubleListNode
	DList DoubleList
}

type DoubleListNode struct {
	key  string
	val  int
	prev *DoubleListNode
	next *DoubleListNode
}

type DoubleList struct {
	head   *DoubleListNode
	tail   *DoubleListNode
	length int
}

/** Initialize your data structure here. */
func Constructor() AllOne {
	//head、tail节点不存具体的数据
	head := &DoubleListNode{
		key: "",
		val: 0,
	}
	tail := &DoubleListNode{
		key: "",
		val: 0,
	}
	head.next = tail
	tail.prev = head
	return AllOne{
		H: make(map[string]*DoubleListNode),
		DList: DoubleList{
			head:   head,
			tail:   tail,
			length: 0,
		},
	}
}

/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
func (this *AllOne) Inc(key string) {
	if node, ok := this.H[key]; ok { //key存在直接加1 需要维护链表有序
		node.val++
		cur := node.next
		for cur != this.DList.tail {
			if cur.val >= node.val { //寻找下一个大于等于node的节点 将node移动到该节点前边
				break
			}
			cur = cur.next
		}
		if node.next != cur {
			this.RemoveNode(node)
			this.InsertNode(node, cur)
		}
	} else { //key不存在 生成节点插在head节点后
		node := &DoubleListNode{
			key: key,
			val: 1,
		}
		node.next = this.DList.head.next
		node.prev = this.DList.head
		this.DList.head.next.prev = node
		this.DList.head.next = node

		this.H[key] = node
		this.DList.length++
	}

}

//删除节点
func (this *AllOne) RemoveNode(node *DoubleListNode) {
	node.prev.next = node.next
	node.next.prev = node.prev
}

//在cur节点前插入node节点
func (this *AllOne) InsertNode(node, cur *DoubleListNode) {
	node.next = cur
	node.prev = cur.prev
	cur.prev.next = node
	cur.prev = node
}

/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
func (this *AllOne) Dec(key string) {
	if node, ok := this.H[key]; ok { //key存在 key不存在不需处理
		if node.val <= 1 { //删除节点
			this.RemoveNode(node)
			this.DList.length--
			delete(this.H, key)
		} else { //节点减1 需要维护链表有序
			node.val--
			cur := node.prev
			for cur != this.DList.tail {
				if cur.val <= node.val { //寻找上一个小于等于node的节点 将node移动到该节点前边
					break
				}
				cur = cur.prev
			}
			if node.prev != cur {
				this.RemoveNode(node)
				this.InsertNode(node, cur)
			}
		}
	}
}

/** Returns one of the keys with maximal value. */
func (this *AllOne) GetMaxKey() string {
	if this.DList.length == 0 {
		return ""
	}
	return this.DList.tail.prev.key
}

/** Returns one of the keys with Minimal value. */
func (this *AllOne) GetMinKey() string {
	if this.DList.length == 0 {
		return ""
	}
	return this.DList.head.next.key
}

第四百三十三题:

class Solution {
public:
    int minMutation(string start, string end, vector<string>& bank) {
        unordered_set<string> S;
        for (auto& s: bank) S.insert(s);
        unordered_map<string, int> dist;
        queue<string> q;
        q.push(start);
        dist[start] = 0;
        char chrs[4] = {'A', 'T', 'C', 'G'};

        while (q.size()) {
            auto t = q.front();
            q.pop();
            for (int i = 0; i < t.size(); i ++ ) {
                auto s = t;
                for (char c: chrs) {
                    s[i] = c;
                    if (S.count(s) && dist.count(s) == 0) {
                        dist[s] = dist[t] + 1;
                        if (s == end) return dist[s];
                        q.push(s);
                    }
                }
            }
        }
        return -1;
    }
};
class Solution {
    int minStepCount = Integer.MAX_VALUE;
    public int minMutation(String start, String end, String[] bank) {
        dfs(new HashSet<String>(), 0, start, end, bank);
        return (minStepCount == Integer.MAX_VALUE) ? -1 : minStepCount;
    }
    private void dfs (HashSet<String> step, int stepCount, 
        String current, String end, String[] bank) {
        if (current.equals(end)) 
            minStepCount = Math.min(stepCount, minStepCount);
        for (String str: bank) {
            int diff = 0;
            for (int i = 0; i < str.length(); i++) 
                if (current.charAt(i) != str.charAt(i))
                    if (++diff > 1) break;
            if (diff == 1 && !step.contains(str)) {
                step.add(str);
                dfs(step, stepCount + 1, str, end, bank);
                step.remove(str);
            }
        }
    }
}
    def minMutation(self, start: str, end: str, bank: List[str]) -> int:
        bank = set(bank)
        if end not in bank:
            return -1

        change_map = {
            "A": "CGT",
            "C": "AGT",
            "G": "CAT",
            "T": "CGA",
        }

        min_count = len(bank) + 1

        def dfs(current, count, current_bank):
            nonlocal min_count

            # terminator
            if count > min_count:
                return
            if current == end:
                if count < min_count:
                    min_count = count
                return
            if not current_bank:
                return

            # process
            for i, s in enumerate(current):
                for char in change_map[s]:
                    new = current[:i] + char + current[i + 1:]
                    if new not in current_bank:
                        continue
                    current_bank.remove(new)
                    # drill down
                    dfs(new, count + 1, current_bank)

                    # reverse state
                    current_bank.add(new)

        dfs(start, 0, bank)

        return min_count if min_count <= len(bank) else -1
func minMutation(start string, end string, bank []string) int {
	result := make([]int, 0)
	dfs(start, end, bank, make([]bool, len(bank), len(bank)), 0, &result)
	sort.Ints(result)    // 从小到达排序,取出最小的值就是最优解。
    if len(result) == 0 {// 如果result的长度等于0,证明dfs中并没有对result进行拼接,就是start无法通过bank变成end
        return -1
    }
	return result[0]

}

// dfs
func dfs(temp string, end string, bank []string, bankVisted []bool, level int, result *[]int) {
	// 结束条件
	if temp == end {
		*result = append(*result, level)
		return
	}
	// 本层处理
	for i := 0; i < len(bank); i++ {
		if !bankVisted[i] && checkDifference(temp, bank[i]) { // 未visited&&相差一个字母
			bankVisted[i] = true // 标记为已读
			dfs(bank[i], end, bank, bankVisted, level+1, result) // 继续递归
			bankVisted[i] = false // 回溯,标记位未读
		}
	}
}
// 比较是否相差一个字母
func checkDifference(temp string, bankByOne string) bool {
	diff :=0
	for i := 0; i < len(temp); i++ {
		if temp[i] !=bankByOne[i] {
			diff++
		}
	}
	if diff == 1 {
		return true
	}
	return false
}

第四百三十四题:

class Solution {
public:
    int countSegments(string s) {
        int res = 0;
        for (int i = 0; i < s.size(); i ++ ) {
            if (s[i] == ' ') continue;
            int j = i + 1;
            while (j < s.size() && s[j] != ' ') j ++ ;
            res ++ ;
            i = j - 1;
        }
        return res;
    }
};
class Solution {
    public int countSegments(String s) {
        String trimmed = s.trim();
        if (trimmed.equals("")) {
            return 0;
        }
        return trimmed.split("\\s+").length;
    }
}
class Solution:
    def countSegments(self, s):
        return len(s.split())
func countSegments(s string) int {
	count := strings.Fields(s)
	return len(count)
}

第四百三十五题:

class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& q) {
        sort(q.begin(), q.end(), [](vector<int> a, vector<int> b) {
            return a[1] < b[1];
        });
        if (q.empty()) return 0;
        int res = 1, r = q[0][1];
        for (int i = 1; i < q.size(); i ++ )
            if (q[i][0] >= r) {
                res ++;
                r = q[i][1];
            }
        return q.size() - res;
    }
};
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals.length == 0) {
            return 0;
        }
        
        Arrays.sort(intervals, new Comparator<int[]>() {
            public int compare(int[] interval1, int[] interval2) {
                return interval1[0] - interval2[0];
            }
        });

        int n = intervals.length;
        int[] f = new int[n];
        Arrays.fill(f, 1);
        for (int i = 1; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                if (intervals[j][1] <= intervals[i][0]) {
                    f[i] = Math.max(f[i], f[j] + 1);
                }
            }
        }
        return n - Arrays.stream(f).max().getAsInt();
    }
}
class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        if not intervals:
            return 0
        
        intervals.sort()
        n = len(intervals)
        f = [1]

        for i in range(1, n):
            f.append(max((f[j] for j in range(i) if intervals[j][1] <= intervals[i][0]), default=0) + 1)

        return n - max(f)
func eraseOverlapIntervals(intervals [][]int) int {
    n := len(intervals)
    if n == 0 {
        return 0
    }
    sort.Slice(intervals, func(i, j int) bool { return intervals[i][0] < intervals[j][0] })
    dp := make([]int, n)
    for i := range dp {
        dp[i] = 1
    }
    for i := 1; i < n; i++ {
        for j := 0; j < i; j++ {
            if intervals[j][1] <= intervals[i][0] {
                dp[i] = max(dp[i], dp[j]+1)
            }
        }
    }
    return n - max(dp...)
}

func max(a ...int) int {
    res := a[0]
    for _, v := range a[1:] {
        if v > res {
            res = v
        }
    }
    return res
}

第四百三十六题:

class Solution {
public:
    vector<int> findRightInterval(vector<vector<int>>& q) {
        int n = q.size();
        for (int i = 0; i < n; i ++ ) q[i].push_back(i);
        sort(q.begin(), q.end());
        vector<int> res(n, -1);
        for (auto& x: q) {
            int l = 0, r = n - 1;
            while (l < r) {
                int mid = l + r >> 1;
                if (q[mid][0] >= x[1]) r = mid;
                else l = mid + 1;
            }
            if (q[r][0] >= x[1]) res[x[2]] = q[r][2];
        }
        return res;
    }
};
class Solution {
    public int[] findRightInterval(int[][] intervals) {
        int[] res = new int[intervals.length];
        Map<int[], Integer> hash = new HashMap<>();
        for (int i = 0; i < intervals.length; i++) {
            hash.put(intervals[i], i);
        }
        Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
        for (int i = 0; i < intervals.length; i++) {
            int min = Integer.MAX_VALUE;
            int minindex = -1;
            for (int j = i + 1; j < intervals.length; j++) {
                if (intervals[j][0] >= intervals[i][1] && intervals[j][0] < min) {
                    min = intervals[j][0];
                    minindex = hash.get(intervals[j]);
                }
            }
            res[hash.get(intervals[i])] = minindex;
        }
        return res;
    }
}
class Solution:
    def findRightInterval(self, intervals: List[List[int]]) -> List[int]:
        n = len(intervals)
        # 排序前给每一项添加索引
        for i in range(n):
            intervals[i].append(i)
        # 按 start 排序
        intervals.sort(key=operator.itemgetter(0))
        res = [-1]*n
        for i in range(n):
            l, r = i+1, n-1
            # 不存在的情况
            if intervals[r][0]<intervals[i][1]:
                continue
            while l<r:
                m = (l+r)//2
                if intervals[m][0]>=intervals[i][1]: r = m
                else: l = m+1
            res[intervals[i][2]] = intervals[r][2]
        return res
type Interval struct {
	start int
	end int
}

type IntervalList []Interval

func (in IntervalList) Len() int {
	return len(in)
}

func (in IntervalList) Less(i, j int) bool {
	return in[i].start <= in[j].start
}

func (in IntervalList) Swap(i, j int) {
	in[i], in[j] = in[j], in[i]
}

func findRightInterval(intervals [][]int) []int {
	if intervals == nil || len(intervals) == 0 {
		return nil
	}
	res := make([]int, len(intervals))
	intervalList := make([]Interval, 0)
	intervalMap := make(map[Interval]int)

	for index, interval := range intervals {
		intervalList = append(intervalList, Interval{
			start: interval[0],
			end:   interval[1],
		})
		intervalMap[Interval{
			start: interval[0],
			end:   interval[1],
		}] = index
	}

	sort.Sort(IntervalList(intervalList))
	for _, interval := range intervalList {
		curNum := interval.end
		tmpIdx := getFirstGreaterOrEqualIdx(intervalList, curNum)
		if tmpIdx == -1 {
			res[intervalMap[interval]] = -1
		} else {
			res[intervalMap[interval]] = intervalMap[intervalList[tmpIdx]]
		}
	}
	return res
}

func getFirstGreaterOrEqualIdx(list []Interval, target int) int {
	low, high := 0, len(list) - 1
	for low <= high {
		mid := low + (high - low) >> 1
		if target <= list[mid].start {
			if (mid == 0) || (list[mid - 1].start < target) {
				return mid
			}
			high = mid - 1
		} else {
			low = mid + 1
		}
	}
	return -1
}

第四百三十七题:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    unordered_map<int, int> cnt;
    int res = 0;

    int pathSum(TreeNode* root, int sum) {
        cnt[0] ++ ;
        dfs(root, sum, 0);
        return res;
    }

    void dfs(TreeNode* root, int sum, int cur) {
        if (!root) return;
        cur += root->val;
        res += cnt[cur - sum];
        cnt[cur] ++ ;
        dfs(root->left, sum, cur), dfs(root->right, sum, cur);
        cnt[cur] -- ;
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int pathSum(TreeNode root, int sum) {
        // key是前缀和, value是大小为key的前缀和出现的次数
        Map<Integer, Integer> prefixSumCount = new HashMap<>();
        // 前缀和为0的一条路径
        prefixSumCount.put(0, 1);
        // 前缀和的递归回溯思路
        return recursionPathSum(root, prefixSumCount, sum, 0);
    }

    /**
     * 前缀和的递归回溯思路
     * 从当前节点反推到根节点(反推比较好理解,正向其实也只有一条),有且仅有一条路径,因为这是一棵树
     * 如果此前有和为currSum-target,而当前的和又为currSum,两者的差就肯定为target了
     * 所以前缀和对于当前路径来说是唯一的,当前记录的前缀和,在回溯结束,回到本层时去除,保证其不影响其他分支的结果
     * @param node 树节点
     * @param prefixSumCount 前缀和Map
     * @param target 目标值
     * @param currSum 当前路径和
     * @return 满足题意的解
     */
    private int recursionPathSum(TreeNode node, Map<Integer, Integer> prefixSumCount, int target, int currSum) {
        // 1.递归终止条件
        if (node == null) {
            return 0;
        }
        // 2.本层要做的事情
        int res = 0;
        // 当前路径上的和
        currSum += node.val;

        //---核心代码
        // 看看root到当前节点这条路上是否存在节点前缀和加target为currSum的路径
        // 当前节点->root节点反推,有且仅有一条路径,如果此前有和为currSum-target,而当前的和又为currSum,两者的差就肯定为target了
        // currSum-target相当于找路径的起点,起点的sum+target=currSum,当前点到起点的距离就是target
        res += prefixSumCount.getOrDefault(currSum - target, 0);
        // 更新路径上当前节点前缀和的个数
        prefixSumCount.put(currSum, prefixSumCount.getOrDefault(currSum, 0) + 1);
        //---核心代码

        // 3.进入下一层
        res += recursionPathSum(node.left, prefixSumCount, target, currSum);
        res += recursionPathSum(node.right, prefixSumCount, target, currSum);

        // 4.回到本层,恢复状态,去除当前节点的前缀和数量
        prefixSumCount.put(currSum, prefixSumCount.get(currSum) - 1);
        return res;
    }
}
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pathSum(self, root: TreeNode, sum: int) -> int:
        #对树做前序遍历同时做前缀和,同时记录祖先中的前缀和,在回溯时删除
        prefix_sum = collections.defaultdict(int) #记录路径中不同前缀和的数量
        prefix_sum[0] = 1 #哨兵,没有节点时和为0
        pre = 0 #从根节点到当前节点位置该路径的前缀和
        ans = 0
        def preOrder(root):
            nonlocal pre,prefix_sum,sum,ans
            if not root:
                return
            pre += root.val
            ans += prefix_sum[pre-sum]
            prefix_sum[pre] += 1

            preOrder(root.left)
            preOrder(root.right)

            prefix_sum[pre] -= 1
            pre -= root.val
        
        preOrder(root)
        return ans
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
// 辅助函数,用于前序遍历二叉树,同时记录下遍历过程中的前进路径和以及出现的次数
// 输入是二叉树,前进路径和,目标值sum,以及辅助哈希表,输出是路径和等于sum的路径数量
func dfs(root *TreeNode, cur, sum int, prefixSum map[int]int) int {
   if root == nil { // 如果树为空
      return 0 // 就返回数量0
   }
   cur += root.Val // 否则前进路径和加上当前节点值进行更新
   // 然后计算前进路径和与目标值sum的差值,并在哈希中查找是否存在
   cnt := 0 // 用0初始化路径数量
   if v, ok := prefixSum[cur-sum]; ok {
      cnt = v // 存在的话就取出对应值,并初始化路径数量,
   }
   // 更新前进路径和cur出现的次数
   prefixSum[cur]++ // 如果是第一次出现则会设置为1
   // 接下来递归求解左右子树,并把返回的路径数量加到cnt上
   cnt += dfs(root.Left, cur, sum, prefixSum)
   cnt += dfs(root.Right, cur, sum, prefixSum)
   prefixSum[cur]-- // 退递归后需要把现在的前进路径和数量-1
   // 下一步要回溯到递归的上一层进行处理
   return cnt // 最后返回路径数量即可
}

// 保存前进路径和的方法 Time: O(n), Space: O(n)
func pathSum(root *TreeNode, sum int) int {
   prefixSum := make(map[int]int)      // 定义辅助哈希表用于存储每个前进路径和以及它出现的次数
   prefixSum[0] = 1                    // 接着把处理边界的0,1数对加入到哈希表
   return dfs(root, 0, sum, prefixSum) // 最后只要调用辅助函数即可
}

第四百三十八题:

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        unordered_map<char, int> cnt;
        for (auto c: p) cnt[c] ++ ;
        vector<int> res;
        int tot = cnt.size();
        for (int i = 0, j = 0, satisfy = 0; i < s.size(); i ++ ) {
            if ( -- cnt[s[i]] == 0) satisfy ++ ;
            while (i - j + 1 > p.size()) {
                if (cnt[s[j]] == 0) satisfy -- ;
                cnt[s[j ++ ]] ++ ;
            }
            if (satisfy == tot) res.push_back(j);
        }
        return res;
    }
};
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int n = s.length(), m = p.length();
        List<Integer> res = new ArrayList<>();
        if(n < m) return res;

        int[] pCnt = new int[26];
        int[] sCnt = new int[26];

        for(int i = 0; i < m; i++){
            pCnt[p.charAt(i) - 'a'] ++;
        }

        int left = 0;
        for(int right = 0; right < n; right++){
            int curRight = s.charAt(right) - 'a';
            sCnt[curRight]++;
            while(sCnt[curRight] > pCnt[curRight]){
                int curLeft = s.charAt(left) - 'a';
                sCnt[curLeft]--;
                left++;
            }
            if(right - left + 1 == m){
                res.add(left);
            }
        }
        return res;
    }
}
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        n, m, res = len(s), len(p), []
        if n < m: return res
        p_cnt = [0] * 26
        s_cnt = [0] * 26

        for i in range(m):
            p_cnt[ord(p[i]) - ord('a')] += 1
        
        left = 0
        for right in range(n):
            cur_right = ord(s[right]) - ord('a')
            s_cnt[cur_right] += 1
            while s_cnt[cur_right] > p_cnt[cur_right]:
                cur_left = ord(s[left]) - ord('a')
                s_cnt[cur_left] -= 1
                left += 1
            if right - left + 1 == m:
                res.append(left)
        return res
func FindAnagrams(s string, p string) []int {
	res := make([]int, 0)
	left := 0       //左指针
	right := 0      //右指针
	lenth := len(s) //字符串长度
	aim := make(map[byte]int)
	now := make(map[byte]int)
	nownum := 0 //当前满足的种类

	for i, _ := range p {
		aim[p[i]] += 1 //记录所有的字符个数
	}
	aimnum := len(aim) //字符种类
	for right <= lenth-1 {
		for nownum != aimnum && right <= lenth-1 {//移动右指针
			if aim[s[right]] != 0 && aim[s[right]] > now[s[right]] {//判断字符是否符合要求,且该种类字符数量尚未满足
				now[s[right]] += 1
				if now[s[right]] == aim[s[right]] {
					nownum += 1
				}

			} else if aim[s[right]] != 0 && aim[s[right]] <= now[s[right]] {//如果该种类字符数量满足了,则只加个数,不加种类数
				now[s[right]] += 1

			}
			right += 1

		}

		for nownum == aimnum && (right-left) <= lenth {//移动左指针
			if right-left == len(p) {//当长度相等,且种类数相等时,一定满足条件
				res = append(res, left)
			}
			if aim[s[left]] != 0 {
				now[s[left]] -= 1
				if now[s[left]] < aim[s[left]] {
					nownum -= 1
				}
			}

			left += 1
		}
	}
	return res
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不能say的秘密

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值