Change post category based on latest posts views

I took the freedom to ignore step #1 and step #3, as they seem being part of your primary approach to achieve your goal and not being your goal itself. I believe you can achieve your goal in a simpler way.

function assign_last_posts_cat_by_views( $posts_number = 50, $delete_last_posts_transient = true ) {
    if ( true === $delete_last_posts_transient ) {
        delete_transient( 'last_posts' );
    }

    if ( ! $posts = get_transient( 'last_posts' ) ) {
        $args = array(
            'numberposts' => $posts_number
        );

        $posts = get_posts( $args ); // Gets your posts...

        set_transient( 'last_posts', $posts, 60*60*24 ); // Caches the result...
    }

    $post_views = array();

    foreach ( $posts as $post ) {
        $post_views[ $post->ID ] = get_post_meta( $post->ID, 'post_views_count', true ); // Gets each post views count...
    }

    arsort( $post_views, SORT_NUMERIC ); // Sorts views in desc order...

    $post_number = 0;

    foreach ( $post_views as $post_id => $views ) {
        if ( $post_number < 5 ) {
            $term_slug = 'large';

        } elseif ( $post_number < 30 ) {
            $term_slug = 'medium';

        } else {
            $term_slug = 'small';
        }

        $term = get_term_by( 'slug', $term_slug, 'category' ); // Gets term and caches it...

        wp_set_post_terms( $post_id, array( $term->term_id ), 'category' ); // Programatically assignes the category to the post...

        $post_number++;
    }
}

Now, as CRON job, to refresh the categories of your last posts every hour without running a new post query, you can do something like this…

add_action( 'hourly_process', 'assign_last_posts_cat_by_views', 10, 2 );
wp_schedule_event( time(), 'hourly', 'hourly_process', array( 50, false ) );

And to run the process when a post is saved…

add_action( 'save_post', 'assign_last_posts_cat_by_views' );